我想执行与特定子类属性匹配的查询,因此我尝试使用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)
不接受。
我对可以直接在 WHERE 子句中声明和使用的内容感兴趣(仅来自 CriteriaBuilder 和/或单个 Root ,就像treat()
子句一样),如果它存在的话。
答案 0 :(得分:4)
<强>更新强>
你期待的sql - 虽然它可以用纯jpa crtieria api进行生成 - 它不会起作用并且会抛出一个异常,因为你(hibernate)不能实例化抽象类主题。
引起:org.hibernate.InstantiationException:无法实例化 抽象类或接口:
如果课程不是抽象的,那就有效。像这样:
CriteriaBuilder b = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Contact> q;
q = b.createQuery(Contact.class);
Root r = q.from(Contact.class);
q.select(r);
q.distinct(true);
q.where(
b.or(
b.like(r.get(Contact_.name),"t%"),
b.and(
b.equal(r.get(Contact_.contact_type),"customer"),
b.like(r.get(Customer_.lastName),"t%")
)
)
);
return getEntityManager().createQuery(q).getResultList();
(我的客户是您的人,我的主题类是联系人类)
以只读方式访问鉴别器列可能是一种有效的解决方法。 如果discriminator_column是contact_type,请执行:
@Column(name = "contact_type",insertable = false,updatable = false)
@XmlTransient
private String contact_type;
然后联系成为一个抽象类,客户作为子类如下:
CriteriaBuilder b = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Contact> q = b.createQuery(Contact.class);
Root<Contact> r = q.from(Contact.class);
q.distinct(true);
q.where(
b.or(
b.like(r.get(Contact_.name), "t%"),
b.and(
b.equal(r.get(Customer_.contact_type), "customer"),
b.like(r.get(Customer_.name), "%t")
)
)
);
return getEntityManager().createQuery(q).getResultList();
制作
select
distinct contact0_.id as id2_1_,
contact0_.contact_type as contact_1_1_,
contact0_.name as name3_1_
from
Contact contact0_
where
contact0_.name like ?
or contact0_.contact_type=?
and (
contact0_.name like ?
)