将已加入的JPA继承引入已存在的数据库中

时间:2012-05-16 05:32:02

标签: hibernate inheritance jpa

这是我找不到解决方案的问题,我想,这要么是不可能的,要么是我对整个想法走向错误的方向。

最初我的JPA层次结构的一部分是这样的:

@MappedSuperclass
public abstract class AbstractEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;
    ..... 
}

@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends AbstractEntity implements Groupable {...}

@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends AbstractEntity implements Groupable {...}

此数据库已经使用了一段时间,直到需要某个对象中的自定义字段出现。

我决定采用以下方式 - 将一个抽象实体作为具有自定义字段的对象的基础:

@Audited
@Entity
@Table(name = "T_CF_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
public abstract class EntityWithCustomFields extends AbstractEntity {...}

@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends EntityWithCustomFields implements Groupable {...}

@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends EntityWithCustomFields implements Groupable {...}

我尝试了不同的选项,总是存在问题:

  1. 我认为JPA提供程序(在我的情况下是hibernate)首先插入父项,因此CF_OBJECT_IDnull

    Hibernate:插入t_cf_object(id,cf_object_id)值(null,?) Hibernate:插入到t_meeting(active,date,c_group,last_notification_date,only_for_members,place,questions_order,subject,update_date,id)值(?,?,?,?,?,?,?,?,?,?)

  2. 如果我在基础实体上省略@PrimaryKeyJoinColumn注释,那么后代的IdId将被用作连接列,它所导致的是子类表没有相同的ID。一开始哪个好,但我们已经在两个表中都有大量记录,它们在id列中具有相同的值。不能在表格中更改id

  3. 在我的情况下使用继承的正确方法是什么,所以它尽可能无缝地进入?很高兴找到我如何首先使hibernate持久化子类实例,然后将其id传递给持久化的超类。对此有必要注释,对吧?

    修改:关于使用@MappedSuperclass

    的建议

    由于以下原因,我无法真正使用@MappedSuperClass。父类EntityWithCustomFields用于通过ManyToOne类的CustomFieldValue关系引用。在代码中它将如下所示:

    @Entity
    @Audited
    @Table(name = "T_CF_VALUES")
    public class CustomFieldValue extends AbstractEntity {
        @ManyToOne
        @JoinColumn(name = "customFieldObject", nullable = false)
        private EntityWithCustomFields customFieldObject;
        ....
    }
    @Audited
    @Entity
    @Table(name = "T_CF_OBJECT")
    @Inheritance(strategy = InheritanceType.JOINED)
    @PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
    public abstract class EntityWithCustomFields extends AbstractEntity {
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "customFieldObject", cascade = CascadeType.ALL)
        private List<CustomFieldValue> customFields;
        ....
     }
    

    我认为@MappedSuperclass不能用于此类内容。

1 个答案:

答案 0 :(得分:0)

在我看来,您不希望在此处实现实体继承,而是为具有自定义字段的实体添加额外的映射超类。

当您具有真正的is-a功能关系时,必须使用实体继承。例如,发票可能包含产品列表,产品实体将是继承树的根(Vegetable,Meat,Clothe等)。在这种情况下,蔬菜是一种产品,当然两种产品可能没有相同的ID,因为价格实体可以通过外键引用产品,如果两种产品具有相同的ID,它就不会干活了。

在您的情况下,具有自定义字段的实体完全不相关。它们碰巧有共同的字段,你想通过将这些公共字段放在一个超类中来考虑它。这就是MappSuperclass的用途。这些自定义字段应该在每个实体表中重复。无论如何,这将比连接继承更有效(这会导致更多查询,更复杂且难以优化查询)。