【问题标题】:@embeddable vs @entity for a mapping a collection@embeddable 与 @entity 用于映射集合
【发布时间】:2012-09-25 03:39:03
【问题描述】:

这一定很幼稚,但我对何时使用@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. 除了直接查询表之外,我不能对可对表执行的嵌入对象执行哪些操作?

注意事项

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

【问题讨论】:

    标签: java spring hibernate jpa orm


    【解决方案1】:

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

    这是一个非常简单的实体类,带有一个@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;
        }
    }
    

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

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

    【讨论】:

    • 谢谢,但我已经阅读了这个article。它没有回答我的问题。我的问题与复合键无关。
    【解决方案2】:
    1. 是否基于我是否希望将 B 类视为单独的表?

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

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

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

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

    可能会删除相应的嵌入实体,但可能会违反完整性约束。

    【讨论】:

    • 我想我可以将 Embeddable 与 ElementCollection 一起使用。我不需要使用@Embedded rt?
    • 第三点:考虑Person包含地址(嵌入),如果两者有单独的表,您可以直接删除关联的地址,但如果Person的表有F.K.要解决,它可能会导致违反完整性约束。
    • '@Embeddable' 使该类有资格嵌入。 '@Embedded' 实际上嵌入了可嵌入实体。
    • en.wikibooks.org/wiki/Java_Persistence/Embeddables 这很好地解释了可嵌入和嵌入
    • 非常感谢.. :) 确实有帮助 :)
    猜你喜欢
    • 1970-01-01
    • 2012-08-12
    • 2020-05-06
    • 2021-11-24
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多