java - 理解 Hibernate 中的 @MapsId 注解

标签 java hibernate jpa

根据 Hibernate documentation , @MapsId 注解的解释如下:

In the embedded id object, the association is represented as the identifier of the associated entity. But you can link its value to a regular association in the entity via the @MapsId annotation. The @MapsId value correspond to the property name of the embedded id object containing the associated entity's identifier. In the database, it means that the Customer.user and the CustomerId.userId properties share the same underlying column (user_fk in this case).

@Entity
class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;

   @MapsId("userId")
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   @OneToOne User user;
}

@Embeddable
class CustomerId implements Serializable {
   UserId userId;
   String customerNumber;

   //implements equals and hashCode
}

@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}

@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;

   //implements equals and hashCode
}

还说:

While not supported in JPA, Hibernate lets you place your association directly in the embedded id component (instead of having to use the @MapsId annotation).

@Entity
class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;
}

@Embeddable
class CustomerId implements Serializable {
   @OneToOne
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   }) 
   User user;
   String customerNumber;

   //implements equals and hashCode
}

@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}

@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;


   //implements equals and hashCode
}

我尝试使用 Hibernate 本身 (hbm2ddl.auto=create) 生成表格,以了解如何使用 @MapsId 注释。以下是我的观察:

如果我的 CustomerUser 实体声明如下:

@Entity
@Table(name="TBL_CUSTOMER")
public class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;

   @MapsId("userId")
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   @OneToOne User user;
}

@Entity 
@Table(name="TBL_USER")
class User {
   @EmbeddedId UserId id;
   Integer age;
}

然后 Hibernate 生成的 DDL 语句说:

Hibernate: create table TBL_CUSTOMER (customerNumber varchar2(255 char) not null, preferredCustomer number(1,0) not null, userfirstname_fk varchar2(255 char) not null, userlastname_fk varchar2(255 char) not null, primary key (customerNumber, userfirstname_fk, userlastname_fk))
Hibernate: create table TBL_USER (firstName varchar2(255 char) not null, lastName varchar2(255 char) not null, age number(10,0), primary key (firstName, lastName))
Hibernate: alter table TBL_CUSTOMER add constraint UK_chvh5mukc81xk9t6fis3skab  unique (userfirstname_fk, userlastname_fk)
Hibernate: alter table TBL_CUSTOMER add constraint FK_chvh5mukc81xk9t6fis3skab foreign key (userfirstname_fk, userlastname_fk) references TBL_USER

现在,如果我将我的 Customer 实体更改为:

@Entity
@Table(name="TBL_CUSTOMER")
public class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;

   @OneToOne User user;
}

那么DDL语句是:

Hibernate: create table TBL_CUSTOMER (customerNumber varchar2(255 char) not null, firstName varchar2(255 char), lastName varchar2(255 char), preferredCustomer number(1,0) not null, user_firstName varchar2(255 char), user_lastName varchar2(255 char), primary key (customerNumber, firstName, lastName))
Hibernate: create table TBL_USER (firstName varchar2(255 char) not null, lastName varchar2(255 char) not null, age number(10,0), primary key (firstName, lastName))
Hibernate: alter table TBL_CUSTOMER add constraint FK_et3bgekef237d4kov7b9oqt85 foreign key (user_firstName, user_lastName) references TBL_USER

在这种情况下,如果我删除 @MapsId@JoinColumn 注释,我会看到 TBL_CUSTOMER 有 2 个额外的列(名字和姓氏)。在这种情况下也没有额外的 alter 命令。

我是 Hibernate 的新手,所以我发现很难理解 Hibernate 文档中给出的解释,@MapsId 的目的是什么,我们何时必须使用它以及它如何影响底层数据库架构。

我也看过这篇 SO 帖子 - can someone please explain me @MapsId in hibernate?但我无法获得有关此注释的明确信息。

最佳答案

@MapsId 用于告诉 hibernate(或任何 JPA 提供程序,实际上)使用与此实体具有一对一关系的另一个实体的相同 ID。

这将避免使用额外的列来存储两个实体之间的引用,同时能够拥有双向关系。

关于java - 理解 Hibernate 中的 @MapsId 注解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25236449/

相关文章:

java - 在Java中覆盖文本文件的一部分

java - Hibernate OneToMany/ManyToOne 导致 SQLGrammarException

java - 使用 hibernate 删除对象后刷新 Jtable?

java - JPA 2.0 没有持久化到 MySQL 中

java - 将 CSS 文件链接到 JSP

java - AndEngine GLES2 中 1 秒过去时,ITimerHandler 减少 2,而不是 1

sql-server - Hibernate + MSSQL + 通过 Contains 进行全文搜索

java - Java 实体的 id 字段的 Long 与 Integer

java - 为什么我们需要双向同步方法?

java - 对象属性限制 - jena