Reputation: 54806
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?
Upvotes: 4
Views: 7926
Reputation: 90447
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 the hibernate.hbm2ddl.auto
property in your configuration uses the default value , which is update
.
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.
Table A: {id, createDate, title, hidden}
Table B: {id, createDate, title, hidden, extraField}
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 the TableA.id
and TableB.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
to create
, then hibernate will delete all tables before generating the table schema .
Upvotes: 4