JPA/Hibernate - InheritanceType.JOINED 的行为类似于 InheritanceType.TABLE_PER_CLASS
我正在尝试在 Hibernate 中实现一个非常简单的继承模型。基本上我有一个可以称为 A
的超类,以及几个继承自 A
的子类。由于我看到的行为对于所有这些都是相同的,因此可以将它们称为 B
。
我想要达到的是所描述的 此处,第 6.2 节。基本上,应该有一个包含其字段的 A
表,以及一个仅包含与子类不同的字段的 B
表,以及一个连接列到 A
的表。我正在使用 Hibernate 的自动模式生成(仅针对开发持久性单元启用)。
然而,当我查看架构时,我看到的是 A
的表,其中包含其字段(正确),以及 B
的表,其中包含以下所有字段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}
...而我得到的是:
Table A: {id, createDate, title, hidden}
Table B: {id, createDate, title, hidden, extraField}
使用 Hibernate 的自动模式生成是不可能的,还是我在某处搞砸了注释?
I'm trying to implement a very simple inheritance model in Hibernate. Basically I have a single superclass which can be called A
, and several subclasses all of which inherit from A
. Since the behavior I'm seeing is the same for all of them, they can just be referred to as B
.
What I'm trying to arrive at is what's described here in section 6.2. Basically, there should be a table for A
that contains its fields, and a table for B
that contains only the fields that are distinct to the subclass, plus a join column back to the table for A
. I am using Hibernate's automatic schema generation (enabled for the development persistence-unit only).
What I see when I look at the schema, however, is a table for A
the contains its fields (correct), and a table for B
which contains all the fields in A
(incorrect), plus the fields added in B
. My classes are annotated as follows:
@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...
}
Any ideas what I've done wrong? Specifically, what I want to see when I look at the generated DB schema is something like:
Table A: {id, createDate, title, hidden}
Table B: {aId, extraField}
...and instead what I get is:
Table A: {id, createDate, title, hidden}
Table B: {id, createDate, title, hidden, extraField}
Is this just not possible using Hibernate's automatic schema generation, or have I screwed up the annotations somewhere?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的注释是正确的,它应该生成您想要的表模式。
但现在您得到了一个不需要的 schema ,它正是使用
每个具体类一个表
策略(即@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
)生成的模式。因此,我认为可能的原因之一是配置中的 hibernate.hbm2ddl.auto 属性使用默认值,即 update 。update
值的行为是:Hibernate 将尝试创建一个
更新脚本以更新数据库
架构到当前映射时
SessionFactory
已创建。如果更新语句不能
执行 ,它将被跳过(对于
向 a 添加非空列的示例
表与现有数据)
Hibernate 不会删除任何数据
更新期间。(例如,如果
列的名称改变了,只是
添加具有新名称的新列,
但仍保留该列
原名)
所以,我认为你必须使用
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
来生成之前的模式,从而产生了以下模式。表 A 和表 B 彼此之间没有任何外键关联。之后,您更改为使用
@Inheritance(strategy = InheritanceType.JOINED)
。在更新模式过程中,hibernate 只是通过在TableA.id
和TableB.id
之间添加外键关联来更新您的模式。它将所有其他列保留在表 B 中。这就是为什么即使您的注释是正确的,您也会获得当前架构。在启动 hibernate 程序之前从数据库中删除表 A 和表 B 后,应生成所需的表模式。或者,您可以将
hibernate.hbm2ddl.auto
设置为create
,然后hibernate将在生成表模式之前删除所有表。Your annotation is correct , it should produce the table schema that you want .
But now you get an undesired schema , which is exactly the schema produced using the
Table per concrete class
strategy (i.e@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
). So , I think one of the possible reason is that thehibernate.hbm2ddl.auto
property in your configuration uses the default value , which isupdate
.The behavior of the
update
value is :Hibernate will try to create an
update script to update the database
schema to the current mapping when
the
SessionFactory
is created.If an update statement cannot be
performed , it will be skipped (For
example adding a not null column to a
table with existing data)
Hibernate will not delete any data
during the update .(For example , if
a column 's name is changed , it just
add an new column with the new name ,
but still keep the column with the
original name)
So , I think you must use
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
to generate the schema before , which produced the following schema . Table A and Table B do not have any foreign key associations to each other.After that , you changed to use
@Inheritance(strategy = InheritanceType.JOINED)
. During the update schema process , hibernate just updated your scheme by adding a foreign key assocation between theTableA.id
andTableB.id
. It kept all other columns in Table B . That 's why you get the current schema even though your annotation is correct .The desired table schema should be generated after you drop Table A and Table B from the DB before starting the hibernate programe . Alternatively , you can set the
hibernate.hbm2ddl.auto
tocreate
, then hibernate will delete all tables before generating the table schema .