@embeddable vs @entity用于映射集合

时间:2012-10-04 06:33:51

标签: java spring hibernate jpa orm

这一定是天真的,但我对何时使用@Entity@Embeddable有疑问。

说我有一个UserNotification类。

 @Entity
 public class User{
     //other properties
     @onetomany
     private List<Notification> notifications;
 }

 @Entity
 public class Notification{
     //properties
 }

我知道会有类UserNotification的表,以及第三个用于映射的表。 如果我这样做怎么办?

 @Entity
 public class User {
     //other properties
     @ElementCollection
     private List<Notification> notifications;
 }

 @Embeddable
 public class Notification{
     //properties
 }

我知道这不会为Notification创建一个表格。但我仍然可以存储我的通知对象。我经历了documentation,但有些怀疑:

  1. 是否基于我是否希望将B类视为单独的表格?
  2. 是否存在创建表和可嵌入对象的性能差异?
  3. 除了直接查询表格之外,我可以用除了表格之外的其他可嵌入对象做什么?
  4. 备注

    对于阅读此问题的任何人,此question也可能对您有所帮助。

2 个答案:

答案 0 :(得分:9)

  1. 是否基于我是否希望将B类视为一个单独的表?
  2. 是的,当您使用@Embedded时,您在@Embeddable类中嵌入了@Entity实体,这使得它可以在@Entity类的同一个表中添加嵌入实体的列

    1. 是否存在创建表和可嵌入对象的性能差异?
    2. 当您使用@Embedded时,对于表创建,需要一个查询,也用于插入和选择行。但是如果你不使用它,则需要多个查询,因此,使用@Embedded会产生更多性能,我们可以说。

      1. 除了直接查询表格之外,我可以用除了表格之外的其他可嵌入对象做什么?
      2. 删除相应的嵌入实体可能是,但可能存在完整性约束违规。

答案 1 :(得分:0)

在JPA中,有几种方法可以创建复合关键字段。让我们使用@Embeddable annotation查看方法 让我们从Entity类开始。

@Entity
@Table
public class TraceRecord {
    @Id
    private TraceRecordPk id;

    @Version
    @Transient
    private int version;

    @Column(columnDefinition = "char")
    private String durationOfCall;

    @Column(columnDefinition = "char")
    private String digitsDialed;

    @Column(columnDefinition = "char")
    private String prefixCalled;

    @Column(columnDefinition = "char")
    private String areaCodeCalled;

    @Column(columnDefinition = "char")
    private String numberCalled;
}

这是一个非常简单的Entity类,带有@Id和@Version字段以及一些@Column定义。没有太多细节,你会看到@Version字段也注释了@Transient。我这样做只是因为我的表也没有跟踪版本的列,但我的数据库是记录的,所以我不太关心版本控制。您还会注意到@Column字段在columnDefinition属性上设置了“char”值。这是因为我表中的字段被定义为char而不是varchar。如果它们是varchar,我不需要这样做,因为String默认情况下映射到varchar字段。

@Id字段是我现在感兴趣的字段。它不是标准的Java类型,而是我自己定义的类。这是上课。

@Embeddable
public class TraceRecordPk implements Serializable {

    private static final long serialVersionUID = 1L;

    @Temporal(TemporalType.DATE)
    @Column
    private Date dateOfCall;

    @Column(columnDefinition="char")
    private String timeOfCall;

    @Column(columnDefinition="char")
    private String callingParty;

    /**
     * Constructor that takes values for all 3 members.
     *
     * @param dateOfCall Date the call was made
     * @param timeOfCall Time the call was made
     * @param callingParty Extension from which the call originated
     */
    public TraceRecordPk(Date dateOfCall, String timeOfCall, String callingParty) {
        this.dateOfCall = dateOfCall;
        this.timeOfCall = timeOfCall;
        this.callingParty = callingParty;
    }
}

要使此类能够成为Entity类的@Id字段,需要使用@Embeddable注释,就像我之前提到的那样。我为复合键选择的3个字段只是普通的@Column定义。我没有为每个字段创建getter / setter,而是简单地实现了一个构造函数,它为所有3个字段获取值,使任何实例都是不可变的。使用@Embeddable注释类时,该类将需要实现Serializable。所以我添加了一个默认的serialVersionUID来容纳。

现在您已经创建了一个使用@Embeddable创建并注释的类,现在可以将其用作Entity类中@Id字段的类型。简单的东西呃。