根据Hibernate documentation,对@MapsId注释的解释为:

在嵌入式id对象中,关联表示为
关联实体的标识符。但是您可以将其值链接到
通过@MapsId注释在实体中进行常规关联。的
@MapsId值对应于嵌入式ID的属性名称
包含关联实体标识符的对象。在数据库中
这意味着Customer.user和CustomerId.userId属性
共享相同的基础列(在这种情况下为user_fk)。

@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
}

还说:

虽然JPA不支持,但Hibernate允许您放置关联
直接在嵌入式id组件中(而不是必须使用
@MapsId注释)。
@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

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

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

我也经历了这个SO帖子-can someone please explain me @MapsId in hibernate?,但是我无法获得有关此批注的清晰信息。

最佳答案

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

这样可以避免使用额外的列来存储两个实体之间的引用,同时又可以具有双向关系。

10-01 03:55