我有一个表,“Quote”,映射在hibernate中,它有一个整数id和日期的复合键,还有几个额外的列。我想编写一个条件查询,使用DetachedCriteria来获取具有最大日期的每个id的行。
在sql中,我可能会编写一个像
这样的查询SELECT * FROM Quote q1
INNER JOIN (SELECT id, max(date) as maxdate FROM Quote
GROUP BY id, date) q2
ON q1.id = q2.id AND q1.date = q2.maxdate
在hibernate中,我认为可以像这样为“group by”子查询创建一个DetachedCriteria(其中Quote是映射表的类,而“Qid”是键的复合id类,具有属性id和date,通过Quote类的“qid”属性访问):
DetachedCriteria maxDateQry = DetachedCriteria.forClass(Quote.class);
maxDateQry.setProjection(
Projections.projectionList()
.add(Projections.max("qid.date", "maxdate"))
.add(Projections.groupProperty("qid.id")));
但是,我不确定如何在标准查询中使用它,该标准查询等同于上面的sql的外部部分。我正在寻找符合
的内容Criteria criteria = session.createCriteria(Quote.class);
criteria.add(
Restrictions.and(
Property.forName("qid.id").eq(maxDateQry???),
Property.forName("qid.date").eq(maxDateQry???)));
List<Quote> quoteList = criteria.list();
上面的两个Property.forName将外表与子查询的相应列相关联。如果内连接只提供一个值,我只需给DetachedCriteria一个Projection并将DetachedCriteria直接传递给Property.forName(...)。eq(..)。我不确定如何在Projection中使用带有两个值(id和maxdate)的DetachedCriteria。
答案 0 :(得分:11)
有完全相同的问题,无法找到多列子查询匹配的确切解决方案。我所做的是重写查询,以便它只需要匹配ONE列上的subselect。而不是
SELECT *
FROM Quote q1
INNER JOIN (
SELECT id, MAX(date) AS maxdate
FROM Quote
GROUP BY id
) q2
ON q1.id = q2.id AND q1.date = q2.maxdate;
尝试:
SELECT *
FROM Quote q1
WHERE q1.date = (SELECT MAX(date) FROM Quote inner where inner.id = q1.id)
关键区别在于JOIN条件的MAX条件现在都在内部SELECT中。
标准/分离标准如下:
DetachedCriteria innerCriteria = DetachedCriteria.forClass(Quote.class, "inner")
.add(Restrictions.eqProperty("inner.id","q1.id"))
.setProjection(Projections.projectionList().add(Projections.max("inner.date")));
DetachedCriteria outerCriteria= DetachedCriteria.forClass(ClmClaim.class, "q1");
outerCriteria.add(Subqueries.propertyEq("q1.date", innerCriteria ));
生成的SQL看起来像:
select
this_.<Blah> as blah2_49_0_,
this_.<Blah> as blah2_50_0_,
this_.<Blah> as blah2_51_0_,
from
Quote this_
where
this_.date = (
select
max(inner_.date) as y0_
from
Quote inner_
where
inner_.claim_number=this_.claim_number
);
你会注意到SQL中没有'group by',因为它不需要。如果子选择中有多个匹配条件,我希望有人在那里。
无论如何,希望它有所帮助。这是我在圣诞节前要做的最后一件事!
答案 1 :(得分:4)
我有一个类似的用例。我非常确定它不能用Criteria完成。 Hibernate不支持from子句中的连接:https://hibernate.atlassian.net/browse/HHH-3356(在编写时仍然打开)。
2013年圣诞节的答案相当不错,但不幸的是,相关的子查询在我的用例中非常糟糕:
但是这个很好(无论如何,对于MySQL 5.6.25):
SELECT * FROM Quote q1
WHERE (q1.id, q1.date) IN
(
SELECT id, max(date)
FROM Quote
GROUP BY id, date
)
我来这里寻找答案
DetachedCriteria maxDateQry = DetachedCriteria.forClass(Quote.class);
maxDateQry.setProjection(
Projections.projectionList()
.add(Projections.groupProperty("qid.id"))
.add(Projections.max("qid.date", "maxdate"))
);
Criteria criteria = session.createCriteria(Quote.class);
Object environmentIdAndStartedDateProperty = "(environmentId, startedDate)" // but not this, some sort of magic
criteria.add(
Subqueries.in(environmentIdAndStartedDateProperty, maxDateQry));
List<Quote> quoteList = criteria.list();
但看起来没有这样的魔法存在。 我不得不放弃并使用hql ,这可能是最好的,因为根据Hibernate 4.2文档,hibernate标准API无论如何都被弃用:https://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/apb.html