Как выполнить неполиморфный запрос HQL в Hibernate?
Я использую Hibernate 3.1.1, и, в частности, я использую запросы HQL.
В соответствии с документацией запросы Hibernate являются полиморфными:
Запрос типа: from Cat as cat
возвращает экземпляры не только Cat
, но и подклассы типа DomesticCat
.
Как я могу запросить экземпляры Cat, но не любого из его подклассов?
Я хотел бы иметь возможность сделать это без явного упоминания каждого подкласса.
Я знаю следующие варианты и не считаю их удовлетворительными:
- Ручная фильтрация экземпляров после запроса OR:
- Вручную добавление предложения WHERE в столбце дискриминатора.
Для Hibernate было бы разумно разрешить пользователю решать, должен ли запрос быть полиморфным или нет, но я не могу найти такой вариант.
Спасибо заранее!
Ответы
Ответ 1
Используйте polymorphism="explicit"
в сопоставление классов. Это заставит запросы возвращать только экземпляры именованного класса, а не его подклассы.
Неявный полиморфизм означает, что экземпляры класса будут возвращаемый запросом, который называет любой суперкласс или реализованный интерфейс или класса, а также экземпляры любого подкласс класса будет возвращен по запросу, который называет класс сам. Явный полиморфизм означает экземпляры класса будут возвращены только по запросам, которые явно называют этот класс.
Ответ 2
SELECT cat FROM Cat cat WHERE cat.class='cat'
где значение 'cat'
является значением дискриминатора класса Cat
.
Если вы используете TABLE_PER_CLASS
, попробуйте cat.class='Cat'
) (имя класса)
Это не является категорией where в столбце дискриминатора, потому что такой запрос будет терпеть неудачу (столбец дискриминатора доступен только в собственных запросах).
Ответ 3
JPA 2 (Hibernate 3.5) добавляет поддержку не полиморфных запросов, это очень похоже на свойство Hibernates.class(как ответил Божо), но он не является Hibernate. Это делается с помощью оператора TYPE. Как и в
Select b from Book b where TYPE(b) = Book
Вы можете больше узнать о здесь в моем блоге
Эяль
Ответ 4
ORM имитирует Java-модель: если объект является экземпляром другого типа (если экземпляр PersianCat также является экземпляром Cat), любой запрос на Cat должен быть полиморфным (представьте, что вы запрашиваете список и спрашиваете если записи соответствуют instanceof Cat
.
Даже решение Bozho несколько нечисто, поскольку столбец "класс" предположительно непрозрачен для вашего отображения спящего режима, хотя я признаю его очень хорошим компромиссом. Вы можете просто получить дискриминатор через простое имя кластера.
Если вы удобно и используете таблицу для каждого класса, вы всегда можете сделать собственный запрос к таблице Cat, чтобы получить идентификаторы, а затем получить записи через спящий режим.
Ответ 5
Посмотрите на BaseQueryReturnFieldsCalculatorGC; он динамически добавляет условие к "where", которое выбирает только, где class= XXX; вы можете дублировать эту логику на HQLQueryTemplate и задать пользователю "isNonPolymorphic".
Обратите внимание, что он будет работать только с табличной иерархией, cos только тогда существует неявный столбец класса и может быть выбран.