Hibernate条件查询,子查询连接两列

Hibernate条件查询,子查询连接两列,hibernate,criteria,detachedcriteria,Hibernate,Criteria,Detachedcriteria,我有一个表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

我有一个表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和日期由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();

其中,上面的两个属性.forName将外部表与子查询的相应列相关联。如果内部联接只提供一个值,我只需给DetachedCriteria一个投影,并将DetachedCriteria直接传递到属性中。。。我不确定如何在投影中使用带有两个值id和maxdate的DetachedCriteria。

有完全相同的问题,无法找到多列子查询匹配的精确解决方案。我所做的是重写查询,这样它只需要在一列上匹配子选择。所以不是

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;
尝试:

关键区别在于连接条件的所有最大条件现在都位于内部选择中

此操作的条件/分离条件如下所示:

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 ));
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语句如下所示:

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 ));
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中没有“分组依据”,因为它不是必需的。如果在子选择中有多个匹配条件,我希望有一个


不管怎样,希望能有帮助。这是圣诞节前我要做的最后一件事

我有一个类似的用例。我很确定这不能用标准来完成。Hibernate不支持from子句中的联接:在编写本文时仍然打开

2013年圣诞节的答案相当不错,但不幸的是,在我的用例中,相关子查询非常糟糕:

使用MySQL 每个id可以有数千个日期 但无论如何,这一个对于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 criteria API已经被弃用了:

这样的魔法实际上是存在的:criteria.addSubqueries.propertiesEqnew String[]{environmentId,startedDate},maxDateQry。但是,它仅在Hibernate 4之后实现: