В Hibernate существует интуитивный и наращиваемый API для критериальных запросов. Сейчас данный API уступает в мощности более зрелым возможностям HQL запросов. В частности, критериальные запросы не поддерживают проекции (projection) и агрегации.
Интерфейс net.sf.hibernate.Criteria представляет запрос по заданному персистентному классу. Фабрикой для создания экземляров Criteria является Session.
Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list();
Индивидуальным критерионом (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} будет подставлено значение синонима запрашиваемой сущности.
Вы можете отсортировать результаты при помощи 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();Вы можете легко специфицировать ограничения для связанных сущюностей используя 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");
}Вы можете специфицировать семантику выборки данных по ассоциациям во время испольнения используя 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.
Класс 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();