是否允许多次在一个Criteria中使用相同的DetachedCriteria?

时间:2015-07-01 10:05:56

标签: java hibernate criteria

我只是想知道在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但我找不到明确的答案。

1 个答案:

答案 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-635HHH-1046,其中Brett Meyer表示:“ Criteria API被视为已弃用”,developers guide (v4.3 §12)表示:

  

Hibernate提供较旧的遗留org.hibernate.Criteria API,应该被视为已弃用。没有功能开发将针对这些API。最终,特定于Hibernate的标准功能将被移植为JPA javax.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