JPA / Hibernate - InheritanceType.JOINED的行为类似于InheritanceType.TABLE_PER_CLASS

时间:2011-05-17 07:46:54

标签: java hibernate jpa

我正在尝试在Hibernate中实现一个非常简单的继承模型。基本上我有一个可以称为A的超类,以及几个继承自A的子类。由于我所看到的行为对于所有这些行为都是相同的,因此它们可以被称为B

我想要达到的是第6.2节中描述的here。基本上,应该有一个A表包含其字段,B表只包含与子类不同的字段,加上一个连接列返回表A 1}}。我正在使用Hibernate的自动模式生成(仅用于开发持久性单元)。

然而,当我查看架构时,我看到的是A包含其字段(正确)的表格,以及B的表格,其中包含{{1}中的所有字段}(不正确),加上A中添加的字段。我的课程注释如下:

B

任何想法我做错了什么?具体来说,当我查看生成的数据库模式时,我想看到的是:

@Entity
@Table(name="A")
@Inheritance(strategy = InheritanceType.JOINED)
public class A implements Serializable {
    protected long id;
    protected Date createDate;
    protected String title;
    protected boolean hidden;

    public A() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreateDate() {
        return createDate;
    }

    @Column(nullable = false)
    public boolean isHidden() {
        return hidden;
    }

    @Column(nullable = false)
    public String getTitle() {
        return title;
    }

    //also setters...   
}

@Entity
@Table(name="B")
@PrimaryKeyJoinColumn(name="aId", referencedColumnName="id")
public class B extends A {
    private String extraField;

    public B() {
        super();
    }

    @Column
    public String getExtraField() {
        return extraField;
    }

    //also setter...
}

...相反,我得到的是:

Table A:  {id, createDate, title, hidden}
Table B:  {aId, extraField}

这是不可能使用Hibernate的自动模式生成,还是我搞砸了某处的注释?

1 个答案:

答案 0 :(得分:4)

您的注释是正确的,它应该生成您想要的表架构。

但是现在你得到了一个不受欢迎的架构,这正是使用Table per concrete class策略生成的架构(即@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS))。因此,我认为可能的原因之一是配置中的hibernate.hbm2ddl.auto属性使用默认值update

update值的行为是:

  • Hibernate将尝试创建一个 更新脚本以更新数据库 架构到当前的映射时 SessionFactory已创建。

  • 如果不能更新语句 执行,它将被跳过(For 例如,向a添加非空列 包含现有数据的表格)

  • Hibernate不会删除任何数据 在更新期间(例如,如果 列的名称已更改,只是 使用新名称添加新列, 但仍然保持列与 原名)

因此,我认为您必须先使用@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)生成架构,这会产生以下架构。表A和表B之间没有任何外键关联。

Table A:  {id, createDate, title, hidden}
Table B:  {id, createDate, title, hidden, extraField}

之后,您更改为使用@Inheritance(strategy = InheritanceType.JOINED)。在更新架构过程中,hibernate刚刚通过在TableA.idTableB.id之间添加外键关联来更新您的方案。它保留了表B中的所有其他列。这就是为什么即使您的注释是正确的,也可以获得当前架构。

在启动hibernate程序之前,从数据库中删除表A和表B后,应生成所需的表模式。或者,您可以将hibernate.hbm2ddl.auto设置为create,然后在生成表模式之前,hibernate将删除所有表。