вторник, 25 апреля 2017 г.



Полиморфные запросы в HQL

Ситуация:

Имеется суперкласс и несколько его наследников, которые в свою очередь содержат в себе другие объекты (разных типов) с каким-нибудь важным значением (например с датой). Необходимо провести поиск по этому значению. Ваш HQL запрос скорее всего будет выглядеть так:

from Parent
where
    Parent.ValueContainerA.valueName > :someValue
    or
    Parent.ValueContainerB.anotherValueName > :someValue)


Проблема:

Для правильного SQL запроса необходимы два left-join между таблицами Parent, ValueContainerA и ValueContainerB. Нужно чтобы HQL протранслировался в следующее:

SELECT...
FROM Parent
    CROSS JOIN ValueContainerA
    CROSS JOIN ValueContainerB
WHERE
    Parent.ValueContainerA_id = ValueContainerA.id
    OR
    Parent.ValueContainerB_id = ValueContainerB.id

В нашем HQL запросе join делается неявно, и по умолчанию хибернейт среди типов join выбирает inner join, а значит он протранслирует HQL в это:

SELECT ...
FROM Parent
    CROSS JOIN ValueContainerA
    CROSS JOIN ValueContainerB
WHERE
    Parent.ValueContainerA_id = ValueContainerA.id
    AND
    Parent.ValueContainerB_id = ValueContainerB.id

Вместо OR получится AND. Такое условие не сможет быть выполнено, и поэтому в результате найдется 0 строк

Решение:

Указать left join явно:

from Parent
    left join ValueContainerA
    left join ValueContainerB
where
    ValueContainerA.valueName > :someValue
    or
    ValueContainer.B.anotherValueName > :someValue