Я пытаюсь немного оптимизировать свои таблицы базы данных. Но мое непонимание Hibernate / JPA сейчас не сильно помогает.
У меня есть объектная модель Java, которая выглядит примерно так:
ParentClass
SubClass1
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubClass2
SubSubClass5
SubSubClass6
Все классы содержат поля. Около 50% всех полей находятся в ParentClass. 40-50% находятся на уровне подкласса 1, а 0-10% находятся на уровне подкласса. Многие из классов SubSubClass * пусты, но необходимы для идентификации типа.
TRY 1:
Так. Сначала мы использовали стратегию TABLE_PER_CLASS в родительском классе. Это привело к огромному количеству таблиц:
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubSubClass5
SubSubClass6
что не очень круто, так как 50% всех столбцов в этих таблицах распределяются между всеми таблицами, а остальные значения делятся между 3-4 таблицами.
TRY 2:
Мы изменили стратегию на SINGLE_TABLE.
Результирующая таблица - это только одна большая таблица "ParentClass". Но поскольку только около 50% всех столбцов распределяются между всеми подклассами, для многих полей должно быть установлено значение Null, что не так уж и сексуально.
TRY 3:
Следующая попытка состояла в том, чтобы смешать стратегию TABLE_PER_CLASS со стратегией SINGLE_TABLE. Я решил не использовать JOIN TABLES в качестве стратегии, поскольку у меня есть много маленьких подклассов, которые могут привести к созданию множества маленьких таблиц с одним или двумя столбцами внутри.
Итак, я следовал за ответами в этом Вопросе: Как смешать стратегии наследования с аннотациями JPA и Hibernate?
Теперь я хотел поместить все значения из ParentClass в одну таблицу, а все значения из первого подуровня в одну таблицу для каждого из них. Это должно привести к такой схеме:
ParentClass
- SubClass1
- SubClass2
- SubClass3
Вот мой код:
@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;
}
Что на самом деле работает довольно хорошо. Но там мои проблемы начались:
Прежде всего я получаю следующие ошибки во время 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
Я думаю, что эти ошибки вызваны тем, что я использую SecondaryTables более одного раза на нескольких уровнях. Каждый раз, когда я их использую, создается другое ограничение. что, конечно, не работает, так как ограничение уже существует.
Вторая проблема заключается в том, что Hibernate сходит с ума, если ему нужно извлечь данные из всех этих таблиц:
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 )
Он объединяет одну и ту же таблицу каждый раз, когда я использовал аннотацию @SecondaryTable в подклассе. Он присоединяется к нему снова и снова. Я взглянул на План объяснения от Oracle, который говорит мне, что этот план автоматически оптимизируется под то, что я бы использовал, если бы я его оптимизировал. но в любом случае. Это странно.
Вопрос:
Как я могу запретить Hibernate создавать одно и то же ограничение несколько раз? Думаю, это также решит проблему объединения. Или следует прекратить попытки сделать это так и есть ли другой способ?