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

33

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

我尝试使用 Projections创建别名来获取 max(colunName) 的值,然后在restrictions.eq()中使用它,但是它一直告诉我"不合法的数字"。

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

8个回答

38

您可以使用DetachedCriteria来表示子查询,就像这样:

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

参考资料


我用过它,但我不满意的是:它需要运行两个查询。再次感谢你。 - Amr Faisal
@AmrFaisal 请看下面我的答案,了解如何使用单个查询完成此操作。 - WhyNotHugo

25

我发现同时使用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以外的方言有效。


2
应谨慎使用,因为带有limitorder by通常比max/min SQL语句 - Cherry

6

使用

addOrder(Order.desc("id"))

并且只获取第一个结果 :)


2
这很糟糕,因为你从数据库中获取整个列表,然后丢弃每个其他记录。如果你有一个巨大的表格,那就不太好了! - Renato Gama
4
不,我说的是获取第一个,这类似于“SELECT ... LIMIT 1”之类的东西(抱歉,我已经很久没有使用Hibernate了)。你所说的是获取多个,只使用第一个;这是不同的事情。 - WhyNotHugo

4

HQL:

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

未经测试。您的数据库需要理解where子句中的子查询。

如果/如何使用criteria api表达这样的子查询太麻烦了。当然,您可以执行两个查询:首先获取最大id,然后获取该id对应的实体。


你很棒,我使用了第二个选项,使用了两个查询,但我在寻找是否可以使用Criteria API完成它 :) - Amr Faisal

0
    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);
    }

0

完全使用Detached Criteria来完成它(因为我喜欢在没有session的情况下构建Detached Criteria)

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

0
更简洁的解决方案是:

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

-2

关于 Hibernate 中的 max() 函数:

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

我认为这只返回了遭遇ID而不是记录对象。 - jamesdeath123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接