Я пытаюсь немного оптимизировать таблицы базы данных. Но мое отсутствие понимания Hibernate/JPA сейчас не очень помогает.Как смешивать стратегии наследования в сочетании с несколькими слоями подкласса
У меня есть объектную модель Java, который выглядит более или менее, как это:
ParentClass
SubClass1
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubClass2
SubSubClass5
SubSubClass6
Все классы содержат поля. Около 50% всех полей находятся в ParentClass. 40-50% находятся на уровне SubClass1 и 0-10% находятся на уровне SubSubclass. Многие классы SubSubClass * являются пустыми, но необходимы для идентификации Type.
TRY 1:
Зв Сначала мы использовали стратегию TABLE_PER_CLASS в Parentclass. Это привело к огромным количеством таблиц:
SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubSubClass5
SubSubClass6
что не очень здорово, так как 50% всех столбцов в этих таблицах распределяются между всеми таблицами и другой Rest разделяется между 3-4 табл.
TRY 2:
Мы изменили стратегию SINGLE_TABLE.
Итоговый стол представляет собой только одну большую таблицу «ParentClass». Но так как только около 50% всех столбцов разделяются между всеми подклассами, для множества полей должно быть установлено значение Null, что не так сексуально.
TRY 3:
Следующая попытка была идти к смешению стратегии TABLE_PER_CLASS с "SINGLE_TABLE" Стратегией. Я решил не использовать JOIN TABLES в качестве стратегии, так как у меня есть много небольших подклассов, которые приведут к созданию множества небольших таблиц с одной или двумя столбцами внутри.
Итак, я следовал за ответы на этот вопрос: How to mix inheritance strategies with JPA annotations and 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 от создания же ограничений несколько раз? Я думаю, что это также устранит проблему соединения. Или должен перестать пытаться сделать это так и есть другой путь?
Мы закончили использование стратегии SINGLE_TABLE. Анализ SQL-запросов показал огромный выигрыш в эффективности. Одна таблица заставляет запрос иметь стоимость 6. Каждая добавленная таблица добавляет 1 Стоимость. При полномасштабном объединении таблицы таблиц мы получим более 150 таблиц, что приведет к 160 стоимости.что в 26 раз больше, чем у одной таблицы. Мы думаем, что мы будем смешивать некоторые вспомогательные таблицы для оптимизации некоторых частей кода. Тесты показали, что это очень аккуратно и не вызывает много проблем, кроме тех, которые я упомянул в своем вопросе (который можно устранить или игнорировать) – user932708