Hibernate генерирует оператор IN при запросе полей подтипов сущности;вызывает проблемы с правильной генерацией запроса при использовании API критериев - PullRequest
0 голосов
/ 28 февраля 2019

Представьте, что у меня есть модель предметной области, которая состоит из 4 классов Fruit (аннотация), Apple, Pear и Kiwi (подклассы Fruit) со столбцом дискриминатора 'type'.Давайте предположим, что класс Apple имеет значение столбца дискриминатора «яблоко», давайте предположим, что «Груша» имеет значение «груша», а киви «киви».Наконец, каждая сущность сопоставляется со стратегией «Таблица на класс», поэтому у нас есть четыре таблицы, представляющие фрукты, яблоки, киви и груши.

В моем случае использования: у меня есть поисковый запрос, который я хотел быделать на мои фрукты.Мы будем искать фрукты, которые созрели, но давайте также предположим, что у яблока есть поле сладости, а у груши - поле толщины, и мы хотели бы найти яблоки, которые являются более чем 10 сладкими, и груши, которые являются более чем 30 толстыми,У нас нет особых требований к нашим киви.

Если бы я использовал API критериев с метамоделью, мне пришлось бы понизить свой объект Root фруктов до соответственно Apple и Pear, чтобы запросить поля, которые у нас есть, которые мы должны протестировать.

Кодпример:

 default List<Fruit> find() {
    return findAll((root, query, cb) -> {
        //Note that we DON'T make a kiwiRoot object here (there's no  need...)
        Root<Apple> appleRoot = cb.treat(root, Apple.class);
        Root<Pear> pearRoot = cb.treat(root, Pear.class);
        //... build up a predicate on the root, apple & pear objects...
}

Теперь реальная проблема заключается в том, что Hibernate генерирует запрос с оператором in , который выбирает только те фрукты, которые я использовал, создавая свой запрос! Таким образом, мы получили бы спелые фрукты, , но только фрукты, которые 10 сладких яблок и 30 груш толщиной !Мы потеряли наши Kiwis на этом пути, потому что Hibernate генерирует оператор IN.

Пример псевдокода SQL:

SELECT ... FROM fruit 
LEFT OUTER JOIN ... (Apples)
LEFT OUTER JOIN ... (Pears)
LEFT OUTER JOIN ... (Kiwi) -- The Kiwis DO get joined in the query though...
WHERE
  fruit.type IN ('apple', 'pear') --Where did our Kiwi go?
  ... -- ripeness, sweetness, thickness check...

Я уже пытался создать предикат OR, где fruit.typeIN ('kiwi'), но тогда запрос путается, скобки не идут туда, куда должны идти ...

PS: Это явно упрощенный пример, реальный код, где возникает эта проблемадействительно нужно использовать API критериев, потому что запрос становится довольно сложным.

1 Ответ

0 голосов
/ 03 марта 2019

Столбец дискриминатора не должен использоваться со стратегией «Таблица на класс».

Тип аннотации DiscriminatorColumn

Указывает столбец дискриминатора для SINGLE_TABLE и JOINEDСтратегии отображения наследования.

https://docs.oracle.com/javaee/7/api/javax/persistence/DiscriminatorColumn.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...