映射集合的@embeddable与@entity

2022-09-02 22:25:36

这一定很天真,但我对何时使用和有疑问。@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

  1. 它是否基于我是否要将类 B 视为单独的表?
  2. 创建表和可嵌入对象时是否存在性能差异?
  3. 除了直接查询表之外,我不能对可嵌入对象执行哪些操作,而对表可以执行哪些操作?

笔记

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


答案 1
  1. 它是否基于我是否要将类 B 视为单独的表?

是的,当您使用 时,您将该实体嵌入到类中,这使得它可以在同一类表中为嵌入实体添加列。@Embedded@Embeddable@Entity@Entity

  1. 创建表和可嵌入对象时是否存在性能差异?

使用 时,创建表时,需要一个查询,插入和选择行也需要一个查询。但是,如果您不使用它,则需要多个查询,因此,我们可以说,使用会产生更高的性能。@Embedded@Embedded

  1. 除了直接查询表之外,我不能对可嵌入对象执行哪些操作,而对表可以执行哪些操作?

删除相应的嵌入式实体可能是,但可能存在为此的完整性约束冲突。


答案 2

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

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

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

这个领域是我现在感兴趣的。它不是标准的Java类型,而是我自己定义的类。这是那个类。@Id

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

若要使此类能够成为实体类上的@Id字段,需要使用@Embeddable对其进行批注,如我前面提到的。我为复合键选择的 3 个字段只是普通@Column定义。我没有为每个字段创建 getters/setters,而是简单地实现了一个构造函数,该构造函数为所有 3 个字段获取值,使任何实例都不可变。使用@Embeddable对类进行批注时,该类需要实现 Serializable。因此,我添加了一个默认的串行VersionUID来适应。

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


推荐