Hibernate генерирует несколько JOIN в запросе с предложением WHERE для сущностей из наследования одной таблицы.JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Hibernate генерирует несколько JOIN в запросе с предложением WHERE для сущностей из наследования одной таблицы.

Сообщение Anonymous »


В нашем приложении мы используем стратегию наследования одной таблицы в режиме гибернации, чтобы различать типы сравнения во время запроса.

Поскольку наше программное обеспечение не является открытым исходным кодом, я постараюсь максимально абстрагировать нашу реализацию.

Наша модель сущности в данном случае состоит из двух таблиц, одна из которых — ParentEntity, имеющая несколько дочерних объектов.

Реализация этих объектов в Java выглядит примерно так:

@Entity @Table(имя = TableEntity.TBL_NAME) общественный класс TableEntity { … } @Сущность @Table(имя = ParentEntity.TBL_NAME) @Inheritance (стратегия = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn (имя = «PARENT_ATTR») публичный абстрактный класс ParentEntity { … } @Сущность @DiscriminatorValue(“CHILD_ENTITY_1) общественный класс ChildEntity1 расширяет ParentEntity { … } @Сущность @DiscriminatorValue("CHILD_ENTITY_2") общественный класс ChildEntity2 расширяет ParentEntity { … } TableEntity — это то, что мы пытаемся запросить.

ParentEntity — это объединенный тип сравнения, помеченный как SingleTableInheritance.

ChildEntity расширяет ParentEntity одним дополнительным полем.

Мы используем стратегию наследования одной таблицы для повышения производительности и потому, что мы не хотим, чтобы количество таблиц в нашей БД переполнялось.

Поскольку мы используем относительно сложный механизм фильтрации, мы объединяем множество предикатов в один более крупный запрос с критериями.

Вызов метода для предиката выглядит примерно так:

Join join = tableEntityRoot.join(TableEntity.joinAttribute); predicates.add(cb.equal(cb.treat(join, ChildEntity1.class).get(ChildEntity1.CHILD_ATTR_1), сравнениеValue)); predicates.add(cb.equal(cb.treat(join, ChildEntity2.class).get(ChildEntity2.CHILD_ATTR_2), сравнениеValue)); TableEntity и ParentEntity объединены.

Предикаты предложенияwhere создаются на основе полей, представленных ChildEntities.

Оператор «обработка» необходим для сопоставления ChildEntities с ParentEntity. В противном случае спящий режим не будет знать, что объединение имеет поля ChildEntities.

При выполнении этого запроса я бы исключил переход в спящий режим для создания одного соединения между TableEntity и ParentEntity, поскольку мы используем стратегию наследования одной таблицы в спящем режиме.

Результирующий запрос выглядит примерно так:

выберите * из ТАБЛИЦЫ t внутреннее соединение PARENT_TABLE pt1 по t.PT_ID = pt1.PT_ID внутреннее соединение PARENT_TABLE pt2 по t.PT_ID = pt2.PT_ID внутреннее соединение PARENT_TABLE pt3 по t.PT_ID = pt3.PT_ID внутреннее соединение PARENT_TABLE pt4 по t.PT_ID = pt4.PT_ID … где (pt1.PARENT_ATTR в (…)) и (p2.CHILD_ATTR_1 = значение сравнения или p3.CHILD_ATTR_2 = значение сравнения или p4.CHILD_ATTR_3 = значение сравнения ); PARENT_TABLE объединяется один раз для каждого имеющегося у него наследования первого уровня. Для одной и той же таблицы существует несколько объединений.

Такое поведение вызывает проблемы при выполнении предложенияwhere, поскольку сами предложения могут быть правильными, а комбинация — нет. В частности, сочетание предложений «где в» и «равно» дает противоречивые результаты.

В частности, проблема возникает из-за оператора «обработка», поскольку без него выполняется только одно соединение. Однако если вы опустите оператор «обработка», спящий режим вызовет исключение, поскольку не сможет найти поля ChildEntity.

Я провел немало исследований по этому поводу в Интернете, но ничего не нашел и сейчас немного в растерянности. Помощь будет оценена по достоинству.
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»