Интерфейс
org.hibernate.Criteria
представляет собой объектно-ориентированный запрос на выборку в отношении конкретной сущности и позволяет выполнять запросы в БД без написания SQL кода. Использование Criteria
является наиболее удачным подходом для интерфейсов поиска с переменным количеством условий. Для создания экземпляров Criteria
используется класс Session
, который выступает в качестве фабрики. Пример создания и обработки Criteria
:
session.beginTransaction(); List<User> users = session.createCriteria(User.class) .setMaxResults(10) .list(); session.getTransaction().commit();
Запрос Criteria должен быть заключен в транзакцию также, как и другие действия с БД
Приведенный выше запрос вернет первые 10 записей из таблицы сущности User
. setMaxResults
представляет собой аналог команды LIMIT
в SQL-запросе. Для того, чтобы выполнить LIMIT
с определенной позиции (LIMIT 2,5
) дополнительно используется метод setFirstResult
:
List<User> users = session.createCriteria(User.class) .setFirstResult(2) .setMaxResults(5) .list();
Условия выборки
Для сужения выборки или, другими словами, задания условий выборки с помощью команды WHERE
в SQL, используется класс org.hibernate.criterion.Restrictions
:
List<User> users = session.createCriteria(User.class) .add(Restrictions.eq("login", login)) .list();
List<User> users = session.createCriteria(User.class) .add(Restrictions.like("name", "Jo", MatchMode.START)) .add(Restrictions.between("weight", minWeight, maxWeight)) .list();
По умолчанию каждое добавленное ограничение присоединяется к условию выборки с операцией and
. Ограничения также могут быть сгруппированы с помощью других логических операций:
List<User> users = session.createCriteria(User.class) .add(Restrictions.or( Restrictions.eq("login", "admin"), Restrictions.gt("rights", 2) )) .add(Restrictions.lt("last_login_date", date)) .list();
List<User> users = session.createCriteria(User.class) .add(Restrictions.and( Restrictions.not( Restrictions.eq("login", "admin") ), Restrictions.le("rights", 2) )) .add(Restrictions.isNotNull("last_login_date")) .list();
Используя класс Restrictions
можно также задавать ограничения в виде SQL выражений:
List<User> users = session.createCriteria(User.class) .add(Restrictions.sqlRestriction( "date_registration < DATE_SUB(CURDATE(),INTERVAL 3 MONTH)") ) .list();
Если в выборке участвуют несколько таблиц, то в SQL выражении можно использовать конструкцию {alias}
, которая будет автоматически заменена псевдонимом из сущности (@Table(name = "users")
):
List<User> users = session.createCriteria(User.class) .add(Restrictions.sqlRestriction( "(SELECT COUNT(*) FROM cars WHERE user_id = {alias}.id) > 2" ) ) .setMaxResults(1) .list();
Сортировка выборки
Сортировка выборки осуществляется с помощью класса org.hibernate.criterion.Order
. Класс Order
представляет собой аналог SQL команды ORDER BY
и также выполняет сортировку в двух направлениях asc
(по возрастанию) и desc
(по убыванию):
List<User> users = session.createCriteria(User.class) .addOrder(Order.desc("id")) .setMaxResults(1) .list();
Выборка из связанных таблиц
В SQL запросах выборки из связанных таблиц происходят с использованием конструкции JOIN
. Для связи таблиц при выборке в Hibernate можно использовать 2 варианта, которые на сегодняшний день практически никак не отличаются. Пример выборки приостановленных абонементов для vip-пользователей:
List<Abonement> abonements = session.createCriteria(Abonement.class) .add(Restrictions.eq("status", AbonementStatus.suspended)) .createAlias("user", "user") .add(Restrictions.ge("user.status", UserStatus.vip)) .setMaxResults(1) .list();
List<Abonement> abonements = session.createCriteria(Abonement.class) .add(Restrictions.eq("status", AbonementStatus.suspended)) .createCriteria("user", "user") .add(Restrictions.ge("user.status", UserStatus.vip)) .setMaxResults(1) .list();
При этом поле "user" в классе сущности Abonement должно быть привязано к соответствующей таблице и полю
По умолчанию таблицы связываются конструкцией INNER JOIN
, для определения типа связи можно использовать дополнительный параметр JoinType
:
.createAlias("user", "user", JoinType.LEFT_OUTER_JOIN)
Очень помогло с простой связкой ManyToOne , а вот с ManyToMany — там где существует связанная таблица, там не очень понятно.
Суда-бы пример биндов классов которые используются, со всеми аннотациями… было-бы очень хорошо.
А вообще — зачет.
Спасибо, через годы ты помогаешь другим 🙂
Очень помог.