I have an entity structure like this:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="CLASS_TYPE", discriminatorType= DiscriminatorType.STRING)
@DiscriminatorValue(value="SUPER")
public class SuperEntity implements Serializable {
private String anyBaseMember;
... blah blah
}
@Entity
@DiscriminatorValue(value="DERIVED")
public class DerivedEntity extends SuperEntity {
private String restrictingMember;
... getter / setter / blah blah
}
Now the intermediate goal is to select all records of the table regardless of the class type, i.e. I have to select all SuperEntity classes, but with a where clause:
CriteriaQuery<SuperEntity> query = criteriaBuilder.createQuery(SuperEntity.class);
Root root = query.from(SuperEntity.class);
query.where(criteriaBuilder.equal(root.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"));
Now, this works very fine an delivers all kinds of entities, SuperEntity and DerivedEntity with the restriction of this certain base member. Now this is where the fun starts: I have to do a further restriction on the restrictingMember of the derived class, if and only if the current record is of that type of the derived class. This is what I tried:
Root root = query.from(SuperEntity.class);
query.where(criteriaBuilder.and(
criteriaBuilder.equal(root.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"),
criteriaBuilder.or(
criteriaBuilder.notEqual(root.type(), DerivedClass.class),
criteriaBuilder.equal(((Path) root.as(DerivedClass.class)).get(DerivedClass_.restrictingMember), "SNAFU")
)
));
To make long things short: It doesn't work:
Exception Description: Invalid query key [restrictingMember] in expression.
It doesn't work, because it seems impossible to cast the root to any other class. At least it doesn't work with .as()
My current approach to get my job done, is to limit only on all members of the SuperClass and then filtering out all other restrictions in a for-loop. Not the state-of-the-art, but my only idea so far.
Edit: Found the solution!
Root rootBase = query.from(SuperEntity.class);
Root rootDerived = query.from(DerivedClass.class);
query.where(criteriaBuilder.and(
criteriaBuilder.equal(rootBase, rootDerived),
criteriaBuilder.equal(rootBase.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"),
criteriaBuilder.or(
criteriaBuilder.notEqual(rootBase.type(), DerivedClass.class),
criteriaBuilder.equal(rootDerived.get(DerivedClass_.restrictingMember), "SNAFU")
)
));
Thanks a lot for your ideas. Ralf