Intuitive et extensible, l'API d'interrogation par critère est désormais offerte par Hibernate. Pour le moment, cette API est moins puissante que l'HQL et toutes les possibilités qu'il offre. En particulier, criteria ne supporte pas la projection ou l'aggrégation.
L'interface net.sf.hibernate.Criteria représente une requête sur une classe persistente donnée. La Session fournit les instances de Criteria.
Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list();
Un criterion (critère de recherche) est une instance de l'interface net.sf.hibernate.expression.Criterion. La classe net.sf.hibernate.expression.Expression définit des méthodes pour obtenir des types de Criterion pré définis.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .add( Expression.between("weight", minWeight, maxWeight) ) .list();
Les expressions peuvent être goupées de manière logique.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .add( Expression.or( Expression.eq( "age", new Integer(0) ), Expression.isNull("age") ) ) .list();
List cats = sess.createCriteria(Cat.class) .add( Expression.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) ) .add( Expression.disjunction() .add( Expression.isNull("age") ) .add( Expression.eq("age", new Integer(0) ) ) .add( Expression.eq("age", new Integer(1) ) ) .add( Expression.eq("age", new Integer(2) ) ) ) ) .list();
Il y a plusieurs types de criterion pré définis (sous classes de Expression), mais l'une d'entre elle particulièrement utile vous permet de spécifier directement du SQL.
List cats = sess.createCriteria(Cat.class) .add( Expression.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) ) .list();
La zone {alias} sera remplacée par l'alias de colonne de l'entité que l'on souhaite intérroger.
Vous pouvez trier les résultats en utilisant net.sf.hibernate.expression.Order.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "F%") .addOrder( Order.asc("name") ) .addOrder( Order.desc("age") ) .setMaxResults(50) .list();
Vous pouvez facilement spécifier des contraintes sur des entités liées, par des associations en utilisant createCriteria().
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "F%") .createCriteria("kittens") .add( Expression.like("name", "F%") .list();
Notez que la seconde createCriteria() retourne une nouvelle instance de Criteria, qui se rapporte aux éléments de la collection kittens.
La forme alternative suivante est utile dans certains cas.
List cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Expression.eqProperty("kt.name", "mt.name") ) .list();
(createAlias() ne créé par de nouvelle instance de Criteria.)
Notez que les collections kittens contenues dans les instances de Cat retournées par les deux précédentes requêtes ne sont pas pré-filtrées par les critères ! Si vous souhaitez récupérer uniquement les kittens qui correspondent à la criteria, vous devez utiliser returnMaps().
List cats = sess.createCriteria(Cat.class) .createCriteria("kittens", "kt") .add( Expression.eq("name", "F%") ) .returnMaps() .list(); Iterator iter = cats.iterator(); while ( iter.hasNext() ) { Map map = (Map) iter.next(); Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS); Cat kitten = (Cat) map.get("kt"); }
Vous pouvez spéficier au runtime le peuplement d'une association en utilisant setFetchMode() (c'est-à-dire le chargement de celle-ci). Cela permet de surcharger les valeurs "lazy" et "outer-join" du mapping.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .setFetchMode("mate", FetchMode.EAGER) .setFetchMode("kittens", FetchMode.EAGER) .list();
Cette requête recherchera mate et kittens via les jointures externes.
La classe net.sf.hibernate.expression.Example vous permet de construire un critère suivant une instance d'objet donnée.
Cat cat = new Cat(); cat.setSex('F'); cat.setColor(Color.BLACK); List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .list();
Les propriétés de type version, identifiant et association sont ignorées. Par défaut, les valeurs null sont exclues.
Vous pouvez ajuster la stratégie d'utilisation de valeurs de l'Exemple.
Example example = Example.create(cat) .excludeZeroes() //exclure les valeurs zéro .excludeProperty("color") //exclure la propriété nommée "color" .ignoreCase() //ne respecte pas la casse sur les chaines de caractères .enableLike(); //utilise like pour les comparaisons de string List results = session.createCriteria(Cat.class) .add(example) .list();
Vous pouvez utiliser les "exemples" pour des critères sur les objets associés.
List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .createCriteria("mate") .add( Example.create( cat.getMate() ) ) .list();