有人可以向我解释一下休眠中的@MapsId吗?

问题描述 投票:0回答:6

有人可以向我解释一下休眠状态下的

@MapsId
吗?我很难理解它。

如果能用一个例子来解释它以及它最适用于哪种用例,那就太好了?

java hibernate jpa annotations hibernate-annotations
6个回答
65
投票

这是来自 Object DB 的很好的解释。

指定为 EmbeddedId 主键、EmbeddedId 主键内的属性或父实体的简单主键提供映射的多对一或一对一关系属性。 value 元素指定关系属性对应的复合键内的属性。如果实体的主键与关系引用的实体的主键具有相同的 Java 类型,则不指定 value 属性。

// parent entity has simple primary key

@Entity
public class Employee {
   @Id long empId;
   String name;
   ...
} 

// dependent entity uses EmbeddedId for composite key

@Embeddable
public class DependentId {
   String name;
   long empid;   // corresponds to primary key type of Employee
}

@Entity
public class Dependent {
   @EmbeddedId DependentId id;
    ...
   @MapsId("empid")  //  maps the empid attribute of embedded id
   @ManyToOne Employee emp;
}

在此处阅读 API 文档


39
投票

我发现这个注释也很有用:

@MapsId
在休眠注释中将一个列与另一个表的列映射。

它还可以用于在两个表之间共享相同的主键。

示例:

@Entity
@Table(name = "TRANSACTION_CANCEL")
public class CancelledTransaction {
    @Id
    private Long id; // the value in this pk will be the same as the
                     // transaction line from transaction table to which 
                     // this cancelled transaction is related

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_TRANSACTION", nullable = false)
    @MapsId
    private Transaction transaction;
    ....
}

@Entity
@Table(name = "TRANSACTION")
@SequenceGenerator(name = "SQ_TRAN_ID", sequenceName = "SQ_TRAN_ID")
public class Transaction  {
    @Id
    @GeneratedValue(generator = "SQ_TRAN_ID", strategy = GenerationType.SEQUENCE)
    @Column(name = "ID_TRANSACTION", nullable = false)
    private Long id;
    ...
}

13
投票

恕我直言,考虑

@MapsId
的最佳方式是当您需要在 n:m 实体中映射复合键时。

例如,客户可以拥有一名或多名顾问,顾问也可以拥有一名或多名客户:

你的实体将是这样的(伪Java代码):

@Entity
public class Customer {
   @Id
   private Integer id;

   private String name;
}

@Entity
public class Consultant {
   @Id
   private Integer id;

   private String name;

   @OneToMany
   private List<CustomerByConsultant> customerByConsultants = new ArrayList<>();

   public void add(CustomerByConsultant cbc) {
      cbc.setConsultant(this);
      this.customerByConsultant.add(cbc);
   }
}

@Embeddable
public class CustomerByConsultantPk implements Serializable {
    
    private Integer customerId;

    private Integer consultantId;
}

@Entity
public class CustomerByConsultant{
   
   @EmbeddedId
   private CustomerByConsultantPk id = new CustomerByConsultantPk();
   
   @MapsId("customerId")
   @JoinColumn(insertable = false, updatable = false)
   private Customer customer;

   @MapsId("consultantId")
   @JoinColumn(insertable = false, updatable = false)
   private Consultant consultant;
}

通过这种方式映射,每当您保存顾问时,JPA 都会自动在

Customer
中插入
Consultant
EmbeddableId
id。所以你不需要手动创建
CustomerByConsultantPk


10
投票

正如 Vladimir 在他的 tutorial 中解释的那样,映射

@OneToOne
关系的最佳方法是使用
@MapsId
。这样,您甚至不需要双向关联,因为您始终可以使用父实体标识符来获取子实体。


6
投票

MapsId 允许您在两个不同的实体/表之间使用相同的主键。注意:当您使用 MapsId 时,

CASCADE.ALL
标志将变得无用,并且您需要确保手动保存您的实体。


0
投票

在回答我的问题时

使用 @ManyToOne JPA Composite Key 用作 Id 来保存实体会添加额外的参数

它展示了

@MapsId
解决映射问题的另一种用法,以及如果不应用
@MapsId
会发生什么。

© www.soinside.com 2019 - 2024. All rights reserved.