Статьи

EasyCriteria — простой способ использования критериев JPA

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

В конце этого поста вы найдете исходный код для загрузки.

Что такое критерии? В настоящее время это лучшее решение для создания динамических запросов. Представьте себе страницу, которая позволяет пользователю выполнять несколько типов запросов; Запрашиваемый запрос может быть по имени, по возрасту или с обоими. Посмотрите ниже, как будет выглядеть запрос, если мы объединяем строку:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";
 
if(parameters[0].equals("name")){
 hql += " and p.name = '" + values[0] + "'";
}
 
if(parameters[1].equals("age")){
 hql += " and p.age = " + values[1];
}
 
TypedQuery<Person> query = em.createQuery(hql, Person.class);
 
System.out.println(query.getResultList());

Обратите внимание, что в приведенном выше коде сделана конкатенация строк; помните, что эта практика плохая и опасная, поскольку она допускает хакерскую атаку «SQL-инъекция». Чтобы избежать этой атаки, мы должны использовать запрос с параметрами:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";
 
if(parameters.contains("name")){
 hql += " and p.name = :name";
}
 
if(parameters.contains("age")){
 hql += " and p.age = :age";
}
 
TypedQuery<Person> query = em.createQuery(hql, Person.class);
 
if(parameters.contains("name")){
 query.setParameter("name", values[0].toString());
}
 
if(parameters.contains("age")){
 query.setParameter("age", Integer.valueOf(values[1].toString()));
}
 
System.out.println(query.getResultList());

Обратите внимание, что проблема SQL-инъекции была решена, но теперь код должен проверить параметры, чтобы добавить его в запрос, а затем передать его значения; для выполнения задачи требуется два «поиска параметров».

У разработчиков Java / Oracle была блестящая идея, когда они создали концепцию Criteria, которая идеально подходит для такой ситуации. Проверьте ниже, как код будет выглядеть с родными критериями JPA:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);
 
if(parameters.contains("name")){
 Path<String> name = root.get("name");
 cq.where(cb.and(cb.equal(name, values[0])));
}
 
if(parameters.contains("age")){
 Path<Integer> name = root.get("age");
 cq.where(cb.and(cb.equal(name, Integer.valueOf(values[1].toString()))));
}
 
TypedQuery<Person> query = em.createQuery(cq);
 
System.out.println(query.getResultList());

Можно увидеть, что передать значения параметров проще. Нет необходимости объединять String или проверять значения списка параметров для заполнения значений.

К сожалению, Criteria API является сложным и многословным до крайности. Если вы хотите сделать только «выберите p из Person p», вам нужно создать критерии ниже:

1
2
3
4
5
6
7
8
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);
 
TypedQuery<Person> query = em.createQuery(cq);
System.out.println(query.getResultList());

Это много кода, чтобы сделать что-то так легко, список всех людей из таблицы.

Чтобы избежать всего этого многословия, был создан проект с открытым исходным кодом EasyCriteria. Если разработчик использует EasyCriteria, запрос выше будет выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
EntityManager em = emf.createEntityManager();
EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);
 
if(parameters.contains("name")){
 easyCriteria.whereEquals("name", values[0]);
}
 
if(parameters.contains("age")){
 easyCriteria.whereEquals("age", values[1]);
}
 
System.out.println(easyCriteria.getResultList());

Обратите внимание, что все детали JPA исчезли. Теперь можно иметь чистый код, проще создавать динамические запросы. О вышеприведенном коде стоит поговорить:

  • Строка 2: экземпляр EasyCriteria создается с помощью «фабрики». Эта фабрика существует для абстракции всех необходимых крутых путей для создания объекта типа EasyCriteriaImp. В будущих версиях будут добавлены новые типы EasyCriteria, например, «Tuple».
  • Строки 5 и 9: параметры легче передать. Чтобы передать параметры для сравнения значений («имя =: имя»), просто используйте метод equals, который принимает в качестве первого параметра имя атрибута; вторым параметром будет значение, которое будет равно.
  • Строка 12: для запуска запроса нет необходимости использовать интерфейс запроса. EasyCriteria сама берет на себя эту ответственность. Можно извлечь результат запроса через EasyCriteria. Для получения результата запроса доступны два метода: EasyCriteria.getSingleResult (), EasyCriteria.getResultList ().

На веб-странице EasyCriteria доступно несколько примеров кода и методы, которые можно использовать. Другим преимуществом EasyCriteria является возможность «связать» все методы:

1
easyCriteria.whereEquals("name", values[0]).whereEquals("age", values[1]).getResultList();

Это легковесная библиотека, потому что единственная зависимость — это JPA, который понадобится системе. Внимание: ваше приложение должно иметь запущенную реализацию JPA.

Эта библиотека была разработана с помощью JUnit и протестирована с Hibernate, OpenJPA и EclipseLink. JUnit также использует платформу Cobertura для проверки, покрыты ли все строки кода (или большая их часть) тестами, поэтому мы получили 100% покрытия.

EasyCriteria все еще находится в бета-версии, но команда разработчиков уже запланировала некоторые выпуски и функции.

Другое преимущество EasyCriteria заключается в том, что ваш программный код больше не «связан» с любым видом реализации JPA. Сегодня Hibernate имеет хороший инструмент критериев, но ваш код должен оставаться «привязанным» к нему. С EasyCriteria вы сможете использовать любую реализацию JPA. Доказательством этой развязанной библиотеки является то, что EasyCriteria была протестирована с 3 реализациями, процитированными ранее.

У EasyCriteria есть методы: в пустых и других. Разработчик сможет сделать объединение (просто простое объединение без параметра), отдельное или даже упорядоченное всеми с помощью Criteria.

Здесь вы найдете EasyCriteria для загрузки и доступ ко всей документации.

Нажмите здесь, чтобы загрузить исходный код этого поста.

Я надеюсь, что этот пост / инструмент может помочь вам.

Ссылка: EasyCriteria — простой способ использования критериев JPA от нашего партнера по JCG Хеберта Коэльо в блоге uaiHebert .