1. Обзор
Querydsl-это обширная платформа Java, которая помогает создавать и запускать типобезопасные запросы на специфичном для домена языке, похожем на SQL .
В этой статье мы рассмотрим Querydsl с помощью API сохранения Java.
Краткое примечание здесь заключается в том, что HQL для Hibernate был первым целевым языком для Querydsl, но в настоящее время он поддерживает JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections и RDFBean в качестве бэкэндов.
2. Подготовка
Давайте сначала добавим необходимые зависимости в наш проект Maven:
2.5.0 com.querydsl querydsl-apt ${querydsl.version} provided com.querydsl querydsl-jpa ${querydsl.version} org.slf4j slf4j-log4j12 1.6.1
А теперь давайте настроим плагин Maven APT:
... ... com.mysema.maven apt-maven-plugin 1.1.3 process target/generated-sources com.querydsl.apt.jpa.JPAAnnotationProcessor
JPAAnnotationProcessor найдет типы доменов, аннотированные javax.persistence.Entity аннотации и генерирует типы запросов для них.
3. Запросы С Помощью Querydsl
Запросы строятся на основе сгенерированных типов запросов, которые отражают свойства типов домена. Кроме того, вызовы функций/методов строятся полностью типобезопасным способом.
Пути запросов и операции одинаковы во всех реализациях, а также интерфейсы Query имеют общий базовый интерфейс.
3.1. Сущность и Тип запроса Querydsl
Давайте сначала определим простую сущность, которую мы будем использовать в примерах:
@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String firstname; @Column private String surname; Person() { } public Person(String firstname, String surname) { this.firstname = firstname; this.surname = surname; } // standard getters and setters }
Querydsl создаст тип запроса с простым именем Person в том же пакете, что и Person . Person может использоваться в качестве статически типизированной переменной в запросах Querydsl в качестве представителя типа Person .
Во – первых – QPerson имеет переменную экземпляра по умолчанию, доступ к которой можно получить в виде статического поля:
QPerson person = QPerson.person;
В качестве альтернативы вы можете определить свои собственные переменные Person следующим образом:
QPerson person = new QPerson("Erich", "Gamma");
3.2. Построение Запроса С Помощью JPA-Запроса
Теперь мы можем использовать JPA Query экземпляры для наших запросов:
JPAQuery query = new JPAQuery(entityManager);
Обратите внимание, что EntityManager является JPA EntityManager .
Давайте теперь извлекем всех людей с именем ” Kent ” в качестве быстрого примера:
QPerson person = QPerson.person; Listpersons = query.from(person).where(person.firstName.eq("Kent")).list(person);
Вызов from определяет источник запроса и проекцию, часть where определяет фильтр и list сообщает Querydsl, чтобы вернуть все совпадающие элементы.
Мы также можем использовать несколько фильтров:
query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));
Или:
query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));
В родной форме JPQL запрос будет написан следующим образом:
select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"
Если вы хотите объединить фильтры с помощью “или”, используйте следующий шаблон:
query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));
4. Упорядочение и агрегирование в Querydsl
Давайте теперь посмотрим, как упорядочение и агрегация работают в библиотеке Querydsl.
4.1. Заказ
Мы начнем с того, что упорядочим наши результаты в порядке убывания по полю фамилия :
QPerson person = QPerson.person; Listpersons = query.from(person) .where(person.firstname.eq(firstname)) .orderBy(person.surname.desc()) .list(person);
4.2. Агрегирование
Теперь давайте воспользуемся простой агрегацией, так как у нас есть несколько доступных (Sum, Avg, Max, Min):
QPerson person = QPerson.person; int maxAge = query.from(person).list(person.age.max()).get(0);
4.3. Агрегирование С Группой По
com.mysema.запрос.группа.Класс GroupBy предоставляет функции агрегирования, которые мы можем использовать для агрегирования результатов запросов в памяти.
Вот краткий пример, где результат возвращается в виде Map с именем в качестве ключа и максимальным возрастом в качестве значения:
QPerson person = QPerson.person; Mapresults = query.from(person).transform( GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));
5. Тестирование С Помощью Querydsl
Теперь давайте определим реализацию DAO с помощью Querydsl – и определим следующую операцию поиска:
public ListfindPersonsByFirstnameQuerydsl(String firstname) { JPAQuery query = new JPAQuery(em); QPerson person = QPerson.person; return query.from(person).where(person.firstname.eq(firstname)).list(person); }
А теперь давайте построим несколько тестов с использованием этого нового DAO и будем использовать Querydsl для поиска вновь созданных Person объектов (реализованных в PersonDao class), а в другом тесте будет проверена агрегация с использованием GroupBy class:
@Autowired private PersonDao personDao; @Test public void givenExistingPersons_whenFindingPersonByFirstName_thenFound() { personDao.save(new Person("Erich", "Gamma")); Person person = new Person("Kent", "Beck"); personDao.save(person); personDao.save(new Person("Ralph", "Johnson")); Person personFromDb = personDao.findPersonsByFirstnameQuerydsl("Kent").get(0); Assert.assertEquals(person.getId(), personFromDb.getId()); } @Test public void givenExistingPersons_whenFindingMaxAgeByName_thenFound() { personDao.save(new Person("Kent", "Gamma", 20)); personDao.save(new Person("Ralph", "Johnson", 35)); personDao.save(new Person("Kent", "Zivago", 30)); MapmaxAge = personDao.findMaxAgeByName(); Assert.assertTrue(maxAge.size() == 2); Assert.assertSame(35, maxAge.get("Ralph")); Assert.assertSame(30, maxAge.get("Kent")); }
6. Заключение
В этом руководстве показано, как создать проект JPA с помощью Querydsl.
Полная реализация этой статьи может быть найдена в проекте github – это проект maven на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.
Краткое примечание здесь: запустите простую сборку maven (mvn clean install), чтобы сгенерировать типы в target/generated-sources , а затем, если вы используете Eclipse, включите папку в качестве исходной папки проекта.