Obtener registro con id máximo, utilizando Criterios de Hibernación


Usando Hibernate's Criteria API, quiero seleccionar el registro dentro de una tabla con el valor máximo para una columna dada.

Traté de usar Proyecciones, crear un alias para max(colunName), luego usarlo en restrictions.eq(), pero sigue diciéndome " número inválido ".

¿Cuál es la forma correcta de hacer eso con Hibernar?

Author: bruno, 2010-10-10

8 answers

Puedes usar un DetachedCriteria para expresar una subconsulta, algo así:

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

Referencias

 36
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-10 14:39:15

Descubrí que usar addOrder y setMaxResults juntos funcionó para mí.

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

Usando el dialecto MySQL, esto genera una instrucción SQL preparada como esta (recortando algunos de los campos):

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

No estoy seguro de si esta solución sería efectiva para dialectos distintos de MySQL.

 21
Author: amacleod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-08 20:47:21

Use

addOrder(Order.desc("id"))

Y obtener solo el primer resultado:)

 6
Author: WhyNotHugo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-07 16:36:01

HQL:

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

Probado. Su base de datos necesita entender las subselecciones en la cláusula where.

Demasiado perezoso para averiguar si/cómo se puede expresar tal subselección con la api de criterios. Por supuesto, puede hacer dos consultas: Primero obtener el id máximo, luego la entidad con ese id.

 1
Author: meriton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-10 12:01:42

La solución más limpia también sería:

DetachedCriteria criteria = DetachedCriteria.forClass(Foo.class).setProjection(Projections.max("id"));
Foo fooObj =(Foo) criteria.getExecutableCriteria(getCurrentSession()).list().get(0);
 0
Author: code chimp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-18 12:57:57
    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
Author: Kumar Abhishek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 07:21:16

Hacerlo completamente con Criterios Separados (porque me gusta construir los criterios separados sin una sesión)

DetachedCriteria maxQuery = DetachedCriteria.forClass(Foo.class)
    .setProjection( Projections.max("id") );
DetachedCriteria recordQuery = DetachedCriteria.forClass(Foo.class)
    .add(Property.forName("id").eq(maxId) );
 0
Author: Daniel Patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-30 19:20:37

Para la función max() en hibernación:

criteria.setProjection(Projections.max("e.encounterId"));
 -2
Author: JEEVA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-13 20:55:19