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

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

2 ответов


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

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

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

...

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

from Cat cat where cat.class = DomesticCat

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

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

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


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