Hibernate Criteria API

Начиная с версии 5.0 собственный Hibernate Criteria API признан устаревшим и не развивается. Вместо него рекомендуется использовать JPA Criteria API.

Начиная с версии 5.2 Hibernate Criteria API объявлен deprecated и не рекомендуется к использованию

Несмотря на вышесказанное страшное предупреждение, родной (устаревший) Criteria API мне нравится больше и кажется более выразительным (и менее типобезопасным, да).

Criteria API это механизм, позволяющий описывать запросы к базе данных используя java код и java объекты. Тем самым это решает проблему генерации запросов исходя из состояния программы.Например, мы заранее не знаем, захочет пользователь фильтровать клиенов по возрасту или не захочет. В случае использования HQL или SQL запросов мы вынуждены будем либо писать два варианта запроса, либо модифицировать код запроса (то есть править текст) во время исполнения. В Criteria API это решается простым условным вызовом метода.

Простые запросы

Все запросы в данном примере основываются на модели данных использованной ранее в примерах HQL и SQL.

Для начала запросим список объектов какого-нибудь класса:

session.createCriteria(Person.class)
  .setMaxResults(10)
  .list()
  .forEach(System.out::println);

Разумеется, в Criteria запросах можно и нужно накладывать условия, по которым объекты будут отбираться:

session.createCriteria(Person.class)
  .add(Restrictions.eq("lastName", "Testoff"))
  .list()
  .forEach(System.out::println);

Связи и коллекции

Сущности в Hibernate могут иметь связи и отношения друг с другом. И на этим связи и отношения можно ссылаться в Criteria API:

session.createCriteria(Passport.class)
  .createCriteria("owner")
    .add(Restrictions.eq("lastName", "Testoff"))
  .list()
  .forEach(System.out::println);

Точно так же можно обратиться и к другой стороне связи, той, где используется коллекция:

session.createCriteria(Person.class)
  .createCriteria("workingPlaces")
    .add(Restrictions.eq("name", "Acme Ltd"))
  .list()
  .forEach(System.out::println);

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

Запросы по примеру выбирают объекты, которые аналогичны заданному:

Passport p = new Passport();
p.setSeries("as");
session.createCriteria(Passport.class)
  .add(Example.create(p).ignoreCase())
  .list()
  .forEach(System.out::println);

DetachedCriteria

Обычно Criteria создаётся в рамках какой-то конкретной сесии и существует в пределах её persistence context. Однако можно создать Criteria, которая не будет привязана к конкретной Session и не присоединена (detached) к persistence context и может быть, в дальнейшем, использована с любым объектом Session. Отчасти таковое поведение напоминает именованные запросы.

session.getTransaction().commit();
session.close();


DetachedCriteria dc = DetachedCriteria.forClass(Person.class)
  .createCriteria("passport")
    .add(Restrictions.eq("series", "AS"));
session = sessionFactory.openSession();
session.beginTransaction();
dc.getExecutableCriteria(session)
  .list()
  .forEach(System.out::println);
session.getTransaction().commit();
session.close();
Person{firstName='Test', lastName='Testoff', dob=2016-07-19, passport=Passport{series='AS', no='123456', issueDate=2016-07-19, validity=P20Y, owner=Testoff}, primaryAddress=Address{city='Kickapoo', street='Main street', building='1', tenants=Test}, workingPlaces=[Company{name='Acme Ltd', workers=Test}]}

DetachedCriteria определяется так же, как обычная Criteria, с той лишь разницей, что её нельзя исполнить. Затем, когда появляется подходящая Session вызовом getExecutableCriteria()  DetachedCriteria преобразуется в обычную Criteria, связанную с этой Session и исполняется.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *