In my model I have an abstract "User" class, and multiple subclasses such as Applicant, HiringManager, and Interviewer. They are in a single table, and I have a single DAO to manage them all.
User:
@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 (for example):
@Entity
@DiscriminatorValue("HIRING_MANAGER")
public class HiringManager extends User ...
Now if I wanted to, say, get all the hiring managers that are not associated with a department, how would I do that? I imagine it would look something like:
DetachedCriteria c = DetachedCriteria.forClass(User.class);
c.add(Restrictions.eq("role", "HIRING_MANAGER"));
c.add(Restrictions.isNull("department"));
List<User> results = getHibernateTemplate().findByCriteria(c);
But when I run this, Hibernate complains "could not resolve property: role" (Which actually makes sense because the User class really doesn't have an explicit role property)
So what's the right way to do what I'm trying to do?
I may be missing something obvious but since you want to find hiring managers, why don't you just pass the HiringManager
subclass as the class to the Criteria
?
Just in case, there is a special class
property that you can use to restrict a query to a subtype. From the Hibernate reference documentation:
14.9. The where clause
...
The special property
class
accesses the discriminator value of an instance in the case of polymorphic persistence. A Java class name embedded in the where clause will be translated to its discriminator value.from Cat cat where cat.class = DomesticCat
You can use this special class property with the Criteria API too, but with a minor change: you have to use the discriminator value as value.
c.add(Restrictions.eq("class", "HIRING_MANAGER"));
Unlike with HQL, it looks like Hibernate is not doing the translation with the Criteria API. I don't really like the idea of using the discriminator value in the code and there is maybe another cleaner way but I'm not aware of it. But it works.