Hibernate ora offre una API di interrogazione per criteri intuitiva ed estensibile. Per ora quest'API è meno potente delle più mature funzionalità di interrogazione HQL. In particolare, le interrogazioni per criteri non supportano la proiezione o l'aggregazione.
L'interfaccia net.sf.hibernate.Criteria rappresenta un'interrogazione nei confronti di una particolare classe persistente. La Session è un produttore di istanze di Criteria.
Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list();
Un criterio individuale di interrogazione è un'istanza dell'interfaccia net.sf.hibernate.expression.Criterion. La classe net.sf.hibernate.expression.Expression definisce metodi "factory" (produttori) per otteere alcuni tipi predefiniti di Criterion.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .add( Expression.between("weight", minWeight, maxWeight) ) .list();
Le espressioni possono essere raggruppate logicamente.
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();
C'è un certo numero di tipi di criterio predefiniti (sottoclassi di Expression ), ma uno di essi è particolarmente utile, perché consente di specificare direttamente dell'SQL.
List cats = sess.createCriteria(Cat.class) .add( Expression.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) ) .list();
il segnaposto {alias} verrà sostituito dall'alias di riga della entità su cui si sta facendo l'interrogazione.
È possibile ordinare i risultati utilizzando 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();
Potete specificare semplicemente vincoli su entità correlate navigando le associazioni utilizzando createCriteria().
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "F%") .createCriteria("kittens") .add( Expression.like("name", "F%") .list();
notate che il secondo createCriteria() restituisce una nuova istanza di Criteria che si riferisce agli elementi della collezione kittens.
La forma alternativa seguente è utile in alcune circostanze.
List cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Expression.eqProperty("kt.name", "mt.name") ) .list();
(createAlias() non crea una nuova istanza di Criteria.)
Notate che le collezioni kittens che appartengono alle istanze di Cat restituita dalle due interrogazioni precedenti non sono pre-filtrate dal criterio! Se volete recuperare solo i gattini che corrispondano al criterio, dovete utilizzare 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"); }
Usando il metodo setFetchMode() è possibile specificare la semantica di caricamento delle associazioni in fase di esecuzione.
List cats = sess.createCriteria(Cat.class) .add( Expression.like("name", "Fritz%") ) .setFetchMode("mate", FetchMode.EAGER) .setFetchMode("kittens", FetchMode.EAGER) .list();
Questa interrogazione caricher sia mate sia kittens tramite join esterni.
La classe net.sf.hibernate.expression.Example permette di costruire un criterio di interrogazione a partire da una data istanza.
Cat cat = new Cat(); cat.setSex('F'); cat.setColor(Color.BLACK); List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .list();
Le proprietà di versione, gli identificatori e le associazioni vengono ignorati. Il comportamento predefinito è di escludere le proprietà di valore null.
Potete impostare come l'Example venga applicato.
Example example = Example.create(cat) .excludeZeroes() //exclude zero valued properties .excludeProperty("color") //exclude the property named "color" .ignoreCase() //perform case insensitive string comparisons .enableLike(); //use like for string comparisons List results = session.createCriteria(Cat.class) .add(example) .list();
Potete anche usare gli esempi per impostare criteri sugli oggetti associati.
List results = session.createCriteria(Cat.class) .add( Example.create(cat) ) .createCriteria("mate") .add( Example.create( cat.getMate() ) ) .list();