Представьте, что у меня есть модель предметной области, которая состоит из 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 критериев, потому что запрос становится довольно сложным.