我只是想知道在Hibernate中是否允许多次在一个Criteria中使用相同的DetachedCriteria对象。想象一下以下情况:
DetachedCriteria dCriteria = DetachedCriteria.forClass(A.class)
.add(Restrictions.eq("id", 1))
.setProjection(Projections.property("id"));
Criteria criteria = session.createCriteria(B.class)
.add(
Restrictions.or(
Restrictions.and(
Subqueries.exists(dCriteria),
Restrictions.eq("id", 1)
),
Restrictions.and(
Subqueries.notExists(dCriteria),
Restrictions.eq("id", 2)
)
)
.setProjection(Projections.property("id"));
是否允许在此标准内使用两次dCriteria?它似乎工作,但我不确定它是否可能导致更复杂的情况下的问题(也许DetachedCriteria在查询生成期间保存相同的状态信息?)。我已经做了一些reasearches但我找不到明确的答案。
答案 0 :(得分:2)
不能(始终)安全地重复使用DetachedCriteria
。例如:获取列表和行数,重用DetachedCriteria
:
DetachedCriteria dc = DetachedCriteria.forClass(A.class);
Criteria c1 = dc.getExecutableCriteria(session);
c1.setProjection(Projections.rowCount());
long count = ((Number) c1.uniqueResult()).longValue();
System.out.println(count + " result(s) found:");
Criteria c2 = dc.getExecutableCriteria(session);
System.out.println(c2.list());
打印:
Hibernate: select count(*) as y0_ from A this_
4 result(s) found:
Hibernate: select count(*) as y0_ from A this_ <-- whoops
[4] <-- whoops again
不会改变DetachedCriteria
的非常简单的事情可能是安全的,但通常将生成包装在某种工厂中,并在每次需要时重新生成它们。
正式地,每次调用DetachedCriteria
时克隆getExecutableCriteria
都不会发生。查看他们的issues,特别是HHH-635和HHH-1046,其中Brett Meyer表示:“ Criteria API被视为已弃用”,developers guide (v4.3 §12)表示:
Hibernate提供较旧的遗留
org.hibernate.Criteria
API,应该被视为已弃用。没有功能开发将针对这些API。最终,特定于Hibernate的标准功能将被移植为JPAjavax.persistence.criteria.CriteriaQuery
的扩展。
编辑:在您的示例中,您在同一查询中重复使用相同的DetachedCriteria。因此,同样的警告适用 - 例如,如果您使用setProjection
使用其中一种用途,则第二次使用时会出错。例如:
DetachedCriteria dCriteria = DetachedCriteria.forClass(A.class)
.add(Restrictions.eq("id", 1))
.setProjection(Projections.property("id"));
Criteria criteria = session.createCriteria(B.class)
.add(
Restrictions.or(
Restrictions.and(
Subqueries.exists(dCriteria
.add(Restrictions.eq("text", "a1")) // <-- Note extra restriction
.setProjection(Projections.property("text"))), // <-- and projection
Restrictions.eq("idx", 1)
),
Restrictions.and(
Subqueries.notExists(dCriteria),
Restrictions.eq("idx", 2)
)
))
.setProjection(Projections.property("id"));
Object o = criteria.list();
这会产生SQL:
select this_.idx as y0_ from B this_
where (
(exists
(select this_.text as y0_ from A this_ where this_.id=? and this_.text=?) and this_.idx=?)
or (not exists
(select this_.text as y0_ from A this_ where this_.id=? and this_.text=?) and this_.idx=?))
我们没有要求text=?
的{{1}}部分,但是由于重复使用了not exists
† <我们得到了它/ p>
† 这会导致以下情况:如果您将DetachedCriteria
应用于.add(Restrictions.eq("text" ...
的两种用途,则会在{{1}中出现两次SQL和
dCriteria