我正在尝试在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的自动模式生成,还是我搞砸了某处的注释?
答案 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.id
和TableB.id
之间添加外键关联来更新您的方案。它保留了表B中的所有其他列。这就是为什么即使您的注释是正确的,也可以获得当前架构。
在启动hibernate程序之前,从数据库中删除表A和表B后,应生成所需的表模式。或者,您可以将hibernate.hbm2ddl.auto
设置为create
,然后在生成表模式之前,hibernate将删除所有表。