Глава 12. Запросы с использованием Criteria

В Hibernate существует интуитивный и наращиваемый API для критериальных запросов. Сейчас данный API уступает в мощности более зрелым возможностям HQL запросов. В частности, критериальные запросы не поддерживают проекции (projection) и агрегации.

12.1. Создание экзепляра Criteria

Интерфейс net.sf.hibernate.Criteria представляет запрос по заданному персистентному классу. Фабрикой для создания экземляров Criteria является Session.

Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(50);
List cats = crit.list();

12.2. Сужение выборки

Индивидуальным критерионом (criterion) является экземпляр интерфейса net.sf.hibernate.expression.Criterion. Класс net.sf.hibernate.expression.Expression определяющий фабричные методы для получения определенных встроеных типов Criterion.

List cats = sess.createCriteria(Cat.class)
.add( Expression.like("name", "Fritz%") )
.add( Expression.between("weight", minWeight, maxWeight) )
.list();

Выражения (expressions) могут быть логически сгрупированны

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

Существует множество типов критерионов (criterion) (подклассы Expression), но с помощью одного из них возможно задавать SQL напрямую.

List cats = sess.createCriteria(Cat.class)
.add( Expression.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) )
.list();

Вместо {alias} будет подставлено значение синонима запрашиваемой сущности.

12.3. Сортировка результатов

Вы можете отсортировать результаты при помощи 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();

12.4. Ассоциации

Вы можете легко специфицировать ограничения для связанных сущюностей используя createCriteria() для навигации по ассоциациям.

List cats = sess.createCriteria(Cat.class)
.add( Expression.like("name", "F%")
.createCriteria("kittens")
.add( Expression.like("name", "F%")
.list();

Учтите, что второй вызов createCriteria() вернет новый экземляр Criteria, который будет укзывать на элемент коллекции kittens.

В определенных случаях используется альтернативная форма (см. ниже).

List cats = sess.createCriteria(Cat.class)
.createAlias("kittens", "kt")
.createAlias("mate", "mt")
.add( Expression.eqProperty("kt.name", "mt.name") )
.list();

(createAlias() не создает нового экземпляра Criteria.)

Учтите, что коллекция kittens содержится в экземплярах объекта Cat возвращаемая предыдущими двумя запросами не фильтруется критериями! Если вам нужно получить только те элементы kittens которые соответсвуют критерию, вы должны использовать 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");
}

12.5. Динамическая выборка по ассоциациям

Вы можете специфицировать семантику выборки данных по ассоциациям во время испольнения используя setFetchMode().

List cats = sess.createCriteria(Cat.class)
.add( Expression.like("name", "Fritz%") )
.setFetchMode("mate", FetchMode.EAGER)
.setFetchMode("kittens", FetchMode.EAGER)
.list();

Этот запрос будет получать mate и kittens используя outer join.

12.6. Запросы по примеру

Класс net.sf.hibernate.expression.Example позволяет вам конструировать критерионы (criterion) запросов из данных заданного экземпляра класса.

Cat cat = new Cat();
cat.setSex('F');
cat.setColor(Color.BLACK);
List results = session.createCriteria(Cat.class)
.add( Example.create(cat) )
.list();

Свойства версии, идентифицаторы и ассоциации игнорируются. По умолчанию, параметры содержащие null значения так же исключаются из сконструированного запроса.

Вы можете настраивать правила работы Example.

Example example = Example.create(cat)
.excludeZeroes() //исключает свойства с нулевыми значениями
.excludeProperty("color")//исключает своство "color"
.ignoreCase()//задает независимое от регистра сравнение строк
.enableLike(); //использует like для сравнения строк
List results = session.createCriteria(Cat.class)
.add(example)
.list();

Вы можете так же использовать примеры для задания критериев ассоциированных объектов.

List results = session.createCriteria(Cat.class)
.add( Example.create(cat) )
.createCriteria("mate")
.add( Example.create( cat.getMate() ) )
.list();