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

В моей модели у меня есть абстрактный класс "Пользователь" и несколько подклассов, таких как 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 жалуется, что "не удалось разрешить свойство: role" (что на самом деле имеет смысл, потому что класс User действительно не имеет явного свойства role)
Итак, какой правильный способ делать то, что я пытаюсь сделать?

Ответы

Ответ 1

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

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

14.9. Предложение where

...

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

from Cat cat where cat.class = DomesticCat

Вы также можете использовать это специальное свойство класса с API-интерфейсом Criteria, но с незначительными изменениями: вы должны использовать значение дискриминатора как значение.

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

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

Ответ 2

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