Получение полиморфных объектов 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 класса при выполнении запроса).