Рубрики
Без рубрики

Руководство по Querydsl с JPA

Краткое руководство по использованию Querydsl с API сохранения Java.

Автор оригинала: baeldung.

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;
List persons = 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;
List persons = 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;   
Map results = 
  query.from(person).transform(
      GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));

5. Тестирование С Помощью Querydsl

Теперь давайте определим реализацию DAO с помощью Querydsl – и определим следующую операцию поиска:

public List findPersonsByFirstnameQuerydsl(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));

    Map maxAge = 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, включите папку в качестве исходной папки проекта.