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

В моей модели у меня есть абстрактный класс "Пользователь" и несколько подклассов, таких как 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 ответа

Решение

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

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

14,9. Пункт где

...

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

from Cat cat where cat.class = DomesticCat

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

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

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

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

Другие вопросы по тегам