我想执行匹配特定子类属性的查询,所以我尝试使用 treat()
.
在这个例子中,我想要:
名称以“a”开头的所有科目,
或所有主体,即人,姓氏以“a”开头
private List<Subject> q1()
{
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Subject> q = b.createQuery(Subject.class);
Root<Subject> r = q.from(Subject.class);
q.select(r);
q.distinct(true);
q.where(
b.or(
b.like(r.get(Subject_.name), "a%"),
b.like(b.treat(r, Person.class).get(Person_.lastName), "a%")));
return em.createQuery(q).getResultList();
}
显然,
Person
扩展 Subject
, Subject
是抽象的,继承是SINGLE_TABLE
, 和 Subject
有 @DiscriminatorOptions(force = true)
由于其他原因(非影响因素)。但是生成的SQL是这样的:
select distinct subject0_.ID as ID2_71_, subject0_.CODE as CODE3_71_, ...
from SUBJECT subject0_
where subject0_.DTYPE='Person' and (subject0_.name like 'a%' or subject0_.lastName like 'a%')
虽然我期待:
select distinct subject0_.ID as ID2_71_, subject0_.CODE as CODE3_71_, ...
from SUBJECT subject0_
where subject0_.name like 'a%' or (subject0_.DTYPE='Person' and subject0_.lastName like 'a%')
有没有办法使用标准构建器生成预期的查询?
请注意
q.from(Person.class)
q.subquery(Person.class)
Not Acceptable .
我对可以直接在 WHERE 子句( 仅从 CriteriaBuilder 和/或单个 Root 产生,就像
treat()
子句)中声明和使用的东西感兴趣,如果它确实存在的话。
最佳答案
解决方案是,使用 Hibernate,在这个特定场景中,非常简单:
private List<Subject> q1()
{
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Subject> q = b.createQuery(Subject.class);
Root<Subject> r = q.from(Subject.class);
q.select(r);
q.distinct(true);
q.where(
b.or(
b.like(r.get(Subject_.name), "a%"),
b.and(
b.equal(r.type(), Person.class),
b.like(((Root<Person>) (Root<?>) r).get(Person_.lastName), "a%"))));
return em.createQuery(q).getResultList();
}
请注意 双铸 ,避免编译错误,并允许在同一个表上执行查询子句。这会产生:
select distinct subject0_.ID as ID2_71_, subject0_.CODE as CODE3_71_, ...
from SUBJECT subject0_
where subject0_.DTYPE in ('Office', 'Team', 'Role', 'Person', ...)
and (subject0_.name like 'a%'
or subject0_.DTYPE='Person' and (subject0_.lastName like 'a%'))
无需更改模型或其他任何内容。
关于hibernate - JPA 条件 API 查询子类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34251930/