Mic*_*tti 11 inheritance hibernate jpa criteria criteria-api
我想执行一个匹配特定子类属性的查询,所以我正在尝试使用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();
}
Run Code Online (Sandbox Code Playgroud)
显然,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%')
Run Code Online (Sandbox Code Playgroud)
虽然我期待:
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%')
Run Code Online (Sandbox Code Playgroud)
有没有办法使用条件构建器生成预期的查询?
注意
q.from(Person.class)q.subquery(Person.class)是不可接受的.
我对可以在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();
}
Run Code Online (Sandbox Code Playgroud)
注意双重转换,它避免了编译错误,并允许在同一个表上执行查询子句.这会产生:
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%'))
Run Code Online (Sandbox Code Playgroud)
无需更改模型或其他任何内容.