Как создать «экземпляр» запроса в JPA 2.0?

Скажем, у нас есть абстрактное @Entity Animal и несколько классов сущностей, расширяющих Animal, включая Dog, Cat, Monkey и Bat.

Как я могу отфильтровать результаты на основе класса расширяющегося объекта?

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

[ ] Dog
[X] Cat
[X] Monkey
[ ] Bat

Теперь я хочу получить объекты с помощью (именованного) запроса, определенного в классе Animal. Какие параметры запроса я могу указать в запросе, чтобы возвращались только объекты Cat и Monkey?


person Kimi    schedule 18.10.2011    source источник


Ответы (2)


Я не совсем уверен, что это поддерживается JPA, но способ сделать это в Hibernate, независимо от стратегии наследования, и, следовательно, даже если у вас нет дискриминатора (или вы не сопоставили его как свойство) состоит в том, чтобы используйте неявное свойство class:

String jpql = "select a from Animal a where a.class in (:classes)";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));

ИЗМЕНИТЬ:

Я только что обнаружил, что это возможно в JPA2 с использованием оператора TYPE:

String jpql = "SELECT a FROM Animal a WHERE TYPE(a) IN :classes";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));
person JB Nizet    schedule 18.10.2011
comment
Это работает, когда вы удаляете скобки вокруг :classes. Спасибо. - person Kimi; 19.10.2011

Вы можете использовать столбец и значение дискриминатора для поиска только определенных подтипов данного типа. По умолчанию имя столбца дискриминатора — DTYPE в JPA, тип — String, а значение — имя класса. Однако вы можете переопределить это, добавив аннотацию уровня класса @DiscriminatorColumn(name="KIND", discriminatorType=DiscriminatorType.INTEGER) (для имени и типа столбца дискриминатора) и @DiscriminatorValue("1") (для конкретного значения дискриминатора для определенного класса). Затем вы можете использовать это в предложении WHERE вашего запроса JPQL, чтобы получить только определенные подтипы, например: WHERE DTYPE="Dog" OR DTYPE="Cat"

person Shivan Dragon    schedule 18.10.2011
comment
Спасибо за ваш ответ! Я попробую ... AND a.dtype IN :dtypes ..., где dtypes — это Collection‹String›, и посмотрю, как пойдет. - person Kimi; 18.10.2011
comment
Если у вас есть проблемы с этим (т. е. со значениями по умолчанию dtype = ClassName), попробуйте добавить аннотации к вашему подклассу, чтобы настроить конкретное имя и значение столбца дискриминатора для каждого подкласса, а затем использовать эти значения в своих запросах. - person Shivan Dragon; 18.10.2011