使用 Hibernate Criteria 获取具有最大 id 的记录

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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();

参考文献

Hibernate 核心参考指南 15.8. Detached queries and subqueries

【讨论】:

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

HQL:

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

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

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

【讨论】:

你是个好人,我确实使用了第二个选项,使用了两个查询,但我正在搜索是否可以使用标准 api 来完成 :)

以上是关于使用 Hibernate Criteria 获取具有最大 id 的记录的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate Criteria API:获取 n 个随机行

如何从 Hibernate Criteria API 获取 SQL(*not* 用于日志记录)

Hibernate Criteria join 查询一对多

Hibernate Criteria 不向表中添加模式

使用 Hibernate 的 Criteria 和 Projections 选择多个不同的列

Hibernate 中Criteria Query查询详解