【问题标题】:Get record with max id, using Hibernate Criteria使用 Hibernate Criteria 获取具有最大 id 的记录
【发布时间】:2011-04-23 10:35:43
【问题描述】:

使用HibernateCriteria API,我想在给定列的最大值的表中选择记录。

我尝试将Projectionscreating an alias 用于max(colunName),然后在restrictions.eq() 中使用它,但它一直告诉我“无效号码”。

使用 Hibernate 的正确方法是什么?

【问题讨论】:

    标签: java hibernate criteria


    【解决方案1】:

    完全使用分离标准(因为我喜欢在没有会话的情况下构建分离标准)

    DetachedCriteria maxQuery = DetachedCriteria.forClass(Foo.class)
        .setProjection( Projections.max("id") );
    DetachedCriteria recordQuery = DetachedCriteria.forClass(Foo.class)
        .add(Property.forName("id").eq(maxId) );
    

    【讨论】:

      【解决方案2】:
          Date maxDateFromDB = null;
          Session session = (Session) entityManager.getDelegate();
      //Register is and Entity and assume maxDateFromDB is a column.
      //Status is another entity with Enum Applied.
      //Code is the Parameter for One to One Relation between Register and Profile entity.
          Criteria criteria = session.createCriteria(Register.class).setProjection(Projections.max("maxDateFromDB") )
          .add(Restrictions.eq("status.id", Status.Name.APPLIED.instance().getId()));
          if(code != null && code > 0) {
              criteria.add(Restrictions.eq("profile.id", code));
          }
          List<Date> list = criteria.list();
      
          if(!CollectionUtils.isEmpty(list)){
              maxDateFromDB = list.get(0);
          }
      

      【讨论】:

        【解决方案3】:

        更清洁的解决方案也是:

        DetachedCriteria criteria = DetachedCriteria.forClass(Foo.class).setProjection(Projections.max("id"));
        Foo fooObj =(Foo) criteria.getExecutableCriteria(getCurrentSession()).list().get(0);
        

        【讨论】:

          【解决方案4】:

          我发现同时使用 addOrdersetMaxResults 对我有用。

          Criteria c = session.createCriteria(Thingy.class);
          c.addOrder(Order.desc("id"));
          c.setMaxResults(1);
          return (Thingy)c.uniqueResult();
          

          使用 MySQL 方言,这会生成一个类似这样的 SQL 准备语句(剪掉一些字段):

          select this_.id ... from Thingy this_ order by this_.id desc limit ?
          

          我不确定这个解决方案是否对 MySQL 以外的方言有效。

          【讨论】:

          • 应该谨慎使用,因为order bylimit一般是slower然后是max/min的sql语句。
          【解决方案5】:

          对于休眠中的max()函数:

          criteria.setProjection(Projections.max("e.encounterId"));
          

          【讨论】:

          • 我认为这只会返回 meetId 而不是记录对象。
          【解决方案6】:

          使用

          addOrder(Order.desc("id"))
          

          只获取第一个结果:)

          【讨论】:

          • 这很糟糕,因为您将整个列表从数据库中取出,然后丢弃所有其他记录。如果您有一张大桌子,那就不是很好了!
          • 不,我说的是获取第一个,这可能是“SELECT ... LIMIT 1”之类的东西(抱歉,很久没有使用hibernate了)。您所说的是获取几个,并且只使用第一个;它们是不同的东西。
          【解决方案7】:

          您可以使用DetachedCriteria 来表达子查询,如下所示:

          DetachedCriteria maxId = DetachedCriteria.forClass(Foo.class)
              .setProjection( Projections.max("id") );
          session.createCriteria(Foo.class)
              .add( Property.forName("id").eq(maxId) )
              .list();
          

          参考文献

          【讨论】:

          • 我用过,但不满意的是:它需要运行两个查询,再次感谢 man
          • @AmrFaisal 请在下面查看我的回答,了解如何使用单个查询执行此操作。
          【解决方案8】:

          HQL:

          from Person where person.id = (select max(id) from Person)
          

          未经测试。您的数据库需要了解 where 子句中的子选择。

          懒得去发现这样的子选择是否/如何用标准 api 来表达。当然,您可以执行两个查询:首先获取最大 id,然后获取具有该 id 的实体。

          【讨论】:

          • 你是个好人,我确实使用了第二个选项,使用了两个查询,但我正在搜索是否可以使用标准 api 来完成 :)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-01-17
          • 1970-01-01
          • 2016-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-08
          相关资源
          最近更新 更多