是否允许在一个 Criteria 中多次使用相同的 DetachedCriteria?
Is it allowed to use the same DetachedCriteria within one Criteria multiple times?
我只是想知道在 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 在查询生成期间保存相同的状态信息?)。我已经做了一些研究,但找不到明确的答案。
不,重复使用并不(总是)安全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
的真正简单的东西可能 是安全的,但通常将生成包装在某种工厂中并重新生成它们你需要它们的时候。
据官方说法,每次调用 getExecutableCriteria
时克隆 DetachedCriteria
永远不会发生。请参阅他们的 issues, particularly HHH-635 and HHH-1046 where Brett Meyer states: "The Criteria API is considered deprecated", and the developers guide (v4.3 §12) 其中指出:
Hibernate offers an older, legacy org.hibernate.Criteria
API which should be considered deprecated. No feature development will target those APIs. Eventually, Hibernate-specific criteria features will be ported as extensions to the 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=?))
我们没有要求 not exists
的 text=?
部分,但由于 DetachedCriteria
†
† 这会导致糟糕的情况,如果您将 .add(Restrictions.eq("text" ...
应用于 dCriteria
的两种用法,它会出现SQL
中的 exists
和 not exists
两次
我只是想知道在 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 在查询生成期间保存相同的状态信息?)。我已经做了一些研究,但找不到明确的答案。
不,重复使用并不(总是)安全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
的真正简单的东西可能 是安全的,但通常将生成包装在某种工厂中并重新生成它们你需要它们的时候。
据官方说法,每次调用 getExecutableCriteria
时克隆 DetachedCriteria
永远不会发生。请参阅他们的 issues, particularly HHH-635 and HHH-1046 where Brett Meyer states: "The Criteria API is considered deprecated", and the developers guide (v4.3 §12) 其中指出:
Hibernate offers an older, legacy
org.hibernate.Criteria
API which should be considered deprecated. No feature development will target those APIs. Eventually, Hibernate-specific criteria features will be ported as extensions to the 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=?))
我们没有要求 not exists
的 text=?
部分,但由于 DetachedCriteria
†
† 这会导致糟糕的情况,如果您将 .add(Restrictions.eq("text" ...
应用于 dCriteria
的两种用法,它会出现SQL
exists
和 not exists
两次