web-dev-qa-db-fra.com

Obtenir l'enregistrement avec max id, en utilisant les critères Hibernate

En utilisant Hibernate 's Criteria API , je souhaite sélectionner l’enregistrement dans une table avec la valeur maximale pour une colonne donnée.

J'ai essayé d'utiliser Projections , en créant un alias pour max(colunName), puis en l'utilisant dans restrictions.eq() , mais il continue de me dire "nombre invalide".

Quelle est la bonne façon de faire cela avec Hibernate?

29
Amr Faisal

Vous pouvez utiliser une DetachedCriteria pour exprimer une sous-requête, comme ceci:

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

Références

36
Pascal Thivent

J'ai trouvé qu'utiliser addOrder et setMaxResults ensemble fonctionnait pour moi.

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

En utilisant le dialecte MySQL, cela génère une instruction SQL préparée à propos de ceci (qui coupe certains champs):

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

Je ne sais pas si cette solution serait efficace pour des dialectes autres que MySQL.

22
amacleod

Utilisation

addOrder(Order.desc("id"))

et chercher juste le premier résultat :)

6
WhyNotHugo

HQL:

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

Non testé. Votre base de données doit comprendre les sous-sélections de la clause where.

Trop paresseux pour savoir si/comment une telle sous-sélection peut être exprimée avec les critères api. Bien sûr, vous pouvez faire deux requêtes: chercher tout d'abord l'id max, puis l'entité avec cet id.

1
meriton

La solution plus propre serait aussi:

DetachedCriteria criteria = DetachedCriteria.forClass(Foo.class).setProjection(Projections.max("id"));
Foo fooObj =(Foo) criteria.getExecutableCriteria(getCurrentSession()).list().get(0);
0
code chimp
    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
Kumar Abhishek

Pour le faire entièrement avec les critères détachés (parce que j'aime construire les critères détachés sans session)

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