有人可以在hibernate中解释我@MapsId吗?

bra*_*ter 60 java annotations hibernate jpa hibernate-annotations

有人可以在hibernate中解释我@MapsId吗?我很难理解它.

如果能用一个例子解释它并且在什么样的用例中它最适用呢?

Man*_*uPK 38

这是Object DB的一个很好的解释.

指定ManyToOne或OneToOne关系属性,该属性提供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;
}
Run Code Online (Sandbox Code Playgroud)

在此处阅读API文档.

  • 但它有什么好处呢?即使没有@MapsId,也可以使用JoinColumn来达到同样的效果,不是吗?如果是这样,这个例子并没有真正说明这个注释真正有用的是什么. (2认同)
  • 由于两个实体将共享相同的主键,因此具有由`@MapsId` 指定的列的实体在持久层(数据库)中将只有主键列。这个想法是在两个实体之间共享主键。 (2认同)

Ton*_*sic 17

我发现这个注释也很有用:@MapsId在hibernate中,注释将列与另一个表的列相映射.

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

例:

@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;
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 在双向关联中我应该将 @MapsId 放在哪里?两个类都应该有“@MapsId”。它甚至有什么区别吗? (2认同)
  • 关于这种使用方式(使用另一个表中的 id 作为其他实体的 id)的好文章在这里 https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and -休眠/ (2认同)

Jau*_*era 13

恕我直言,最好的思考方式@MapsId是当您需要在 an: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;
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式映射,每当您保存顾问时,JPA 都会自动插入Customerid 。所以你不需要手动创建.ConsultantEmbeddableIdCustomerByConsultantPk


BER*_*ine 6

正如他在他的教程中解释 Vladimir的那样,映射 @OneToOne 关系的最佳方法是使用 @MapsId。这样,您甚至不需要双向关联,因为您始终可以使用父实体标识符获取子实体。


Jan*_*ena 6

MapsId 允许您在两个不同的实体/表之间使用相同的主键。注意:当您使用 MapsId 时,该CASCADE.ALL标志将变得无用,您将需要确保手动保存您的实体。