I am trying to optimize my database tables a bit. But my lack of understanding of Hibernate/JPA is not much of a help right now.
I have a Java Object Model which looks more or less like this:
ParentClass
SubClass1
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubClass2
SubSubClass5
SubSubClass6
All the Classes contain Fields. About 50% of all Fields are in the ParentClass. 40-50% are on the SubClass1 Level and 0-10% are in the SubSubclass Level. Many of the SubSubClass* classes are empty but are required for identifying the Type.
TRY 1:
So. What we did first, was using a TABLE_PER_CLASS Strategy on the Parentclass. This resulted in a huge amount of Tables:
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubSubClass5
SubSubClass6
which is not very cool, since 50% of all Columns in these Tables are shared between all Tables and the other Rest is shared between 3-4 Tables.
TRY 2:
We Changed the Strategy to SINGLE_TABLE.
The resulting table is just one big "ParentClass" Table. But since only about 50% of all Columns are shared between all Subclasses, lots of Fields have to be set to Null, which is not that sexy.
TRY 3:
The Next try was going towards mixing the TABLE_PER_CLASS Strategy with the "SINGLE_TABLE" Strategy. I decided against using JOIN TABLES as a Strategy since I have to many small subclasses which would cause the creation of many many small tables with one or two Columns inside.
So, I was following answers in this Question: How to mix inheritance strategies with JPA annotations and Hibernate?
I wanted now to put all Values from the ParentClass in one table and all values from the first SubLevel into one table for each of them. This should result in a Schema like this:
ParentClass
- SubClass1
- SubClass2
- SubClass3
Here is my code:
@MappedSuperclass
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class ParentClass {
private String value1;
}
@MappedSuperclass
@SecondaryTable(name = "SubClass1")
public abstract class SubClass1 extends ParentClass {
@Column(table = "SubClass1")
private String value11;
}
@MappedSuperclass
@SecondaryTable(name = "SubClass2")
public abstract class SubClass2 extends ParentClass {
@Column(table = "SubClass2")
private String value12;
}
@Entity
@SecondaryTable(name = "SubClass1")
public abstract class SubSubClass1 extends SubClass1 {
@Column(table = "SubClass1")
private String value111;
}
@Entity
@SecondaryTable(name = "SubClass2")
public abstract class SubSubClass2 extends SubClass2 {
@Column(table = "SubClass2")
private String value121;
}
Which actually works quite well. But there my problems started:
First of all I get the following Errors during the SchemaUpdate.
Unsuccessful: alter table schema.SubClass1 add constraint AAAAAAA36D68C4 foreign key (id) references schema.ParentClass
ORA-02275: such a referential constraint already exists in the table
Unsuccessful: alter table schema.SubClass2 add constraint AAAAAAA36D68C4 foreign key (id) references schema.ParentClass
ORA-02275: such a referential constraint already exists in the table
I think these errors are caused since, I am using the SecondaryTables more than once on multiple Levels. For each time I use them, another constraint is being created. which does not work of course, since the constraint already exists.
The Second Problem is the fact that Hibernate goes crazy if it should fetch the data from all those Tables:
select
*
from
( select
parentclass0_.value1 as value1_1_,
parentclass0_1_.value11 as erste1_3_,
parentclass0_1_.value111 as value1113_3_,
parentclass0_2_.value12 as value122_3_,
parentclass0_2_.value121 as value1214_3_,
parentclass0_.DTYPE as DTYPE2_
from
schema.parentclass parentclass0_
left outer join
schema.subclass1 parentclass0_1_
on parentclass0_.id=parentclass0_1_.id
left outer join
schema.subclass1 parentclass0_2_
on parentclass0_.id=parentclass0_2_.id
left outer join
schema.subclass1 parentclass0_3_
on parentclass0_.id=parentclass0_3_.id
left outer join
schema.subclass2 parentclass0_4_
on parentclass0_.id=parentclass0_4_.parentclass_id
left outer join
schema.subclass1 parentclass0_5_
on parentclass0_.id=parentclass0_5_.id
left outer join
schema.subclass1 parentclass0_6_
on parentclass0_.id=parentclass0_6_.id )
It joins the same table for each time i used the @SecondaryTable annotation in a subclass. It joins it again and again. I had a look at the Explain Plan from Oracle which tells me that this plan is automatically optimized to what I would use if i would optimize it. but anyway. Its strange.
The Question:
How can i prevent Hibernate from creating the same constraint multiple times? I think this would also fix the join problem. Or should stop trying to do it like this and is there another way?