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();