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?
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();
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.
Utilisation
addOrder(Order.desc("id"))
et chercher juste le premier résultat :)
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.
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);
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);
}
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) );