首页 文章

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

提问于
浏览
10

我有一个表,“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,由a访问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 .

2 回答

  • 10

    有完全相同的问题,无法找到多列子查询匹配的确切解决方案 . 我所做的是重写查询,以便它只需要匹配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',因为它不需要 . 如果子选择中有多个匹配条件,我希望有人在那里 .

    无论如何,希望它有所帮助 . 这是我在圣诞节前要做的最后一件事!

  • 3

    我有一个类似的用例 . 我用Criteria完成了 . Hibernate不支持from子句中的连接:https://hibernate.atlassian.net/browse/HHH-3356(在编写时仍然打开) .

    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();
    

    但看起来没有这样的魔法存在 . I had to give up and use hql ,这可能是最好的,因为根据Hibernate 4.2文档,hibernate标准API无论如何都被弃用:https://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/apb.html

相关问题