我有一个这样的实体结构:
@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
}
现在的中间目标是选择表中的所有记录,而不考虑类类型,即我必须选择所有SuperEntity类,但使用where子句:
CriteriaQuery<SuperEntity> query = criteriaBuilder.createQuery(SuperEntity.class);
Root root = query.from(SuperEntity.class);
query.where(criteriaBuilder.equal(root.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"));
现在,这工作得很好,并在这个特定基础成员的限制下提供了各种实体,SuperEntity和DerivedEntity。现在,乐趣就从这里开始了:我必须对派生类的restrictingMember做进一步的限制,当且仅当当前记录是派生类的那个类型。这就是我尝试的:
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")
)
));
长话短说:它不起作用:
Exception Description: Invalid query key [restrictingMember] in expression.
它不起作用,因为似乎不可能将根投射到任何其他类。至少它不适用于.as()
我目前完成工作的方法是只限制SuperClass的所有成员,然后在for循环中过滤掉所有其他限制。不是最先进的,但我到目前为止唯一的想法。
编辑:找到解决方案!
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")
)
));
非常感谢你的想法。Ralf
我知道您可以使用"class"属性在命名查询中查询鉴别器值,就像在select e from SuperEntity e where e.class ='DERIVED'
中一样。我知道它没有使用标准,但也许它会有所帮助。