Получение полиморфных объектов гибернации с помощью запроса критериев - PullRequest
14 голосов
/ 08 июля 2010

В моей модели у меня есть абстрактный класс «Пользователь» и несколько подклассов, таких как Applicant, HiringManager и Interviewer. Они находятся в одной таблице, и у меня есть один DAO для управления ими всеми.

Пользователь:

@Entity
@Table(name="User")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="role",
    discriminatorType=DiscriminatorType.STRING
)
public abstract class User extends BaseObject implements Identifiable<Long> ...

HiringManager (например):

@Entity
@DiscriminatorValue("HIRING_MANAGER")
public class HiringManager extends User ...

Теперь, если бы я хотел, скажем, получить всех менеджеров по найму, которые не связаны с отделом, как бы я это сделал? Я думаю, это будет выглядеть примерно так:

DetachedCriteria c = DetachedCriteria.forClass(User.class);
c.add(Restrictions.eq("role", "HIRING_MANAGER"));
c.add(Restrictions.isNull("department"));
List<User> results = getHibernateTemplate().findByCriteria(c);

Но когда я запускаю это, Hibernate жалуется, что «не может разрешить свойство: роль» (что на самом деле имеет смысл, поскольку класс User действительно не имеет явного свойства роли) Так как правильно делать то, что я пытаюсь сделать?

Ответы [ 2 ]

20 голосов
/ 08 июля 2010

Возможно, мне не хватает чего-то очевидного, но, поскольку вы хотите найти менеджеров по найму, почему бы вам просто не передать подкласс HiringManager в качестве класса Criteria?

На всякий случай есть специальное свойство class, которое можно использовать для ограничения запроса подтипом. Из справочной документации по Hibernate:

14,9. Пункт where

...

Специальное свойство class Доступ значение дискриминатора экземпляра в случае полиморфного упорство. Имя класса Java встроен в пункт, где будет переводится в значение дискриминатора.

from Cat cat where cat.class = DomesticCat

Это специальное свойство класса можно использовать и с Criteria API, но с небольшим изменением: вы должны использовать значение дискриминатора в качестве значения.

c.add(Restrictions.eq("class", "HIRING_MANAGER"));

В отличие от HQL, похоже, что Hibernate не выполняет перевод с помощью Criteria API. Мне не очень нравится идея использования значения дискриминатора в коде, и, возможно, есть другой более чистый способ, но я не знаю об этом. Но это работает.

1 голос
/ 10 июля 2012

Обратите внимание, что это также работает для отображений наследования объединенного подкласса с одним предупреждением.Класс, используемый в Ограничении, должен быть конкретным классом.Если у вас есть такая модель, как Animal <- Mammal <- Cat, вы не можете набрать <code>Restrictions.eq("class", Mammal.class); и рассчитываете получить обратно всех млекопитающих.Вместо этого мне пришлось перебором, используя Restrictions.or или все известные конкретные классы (использование Restrictions.in () дало исключение приведения класса при выполнении запроса).

...