Um guia para Querydsl com JPA

Um guia para Querydsl com JPA

1. Visão geral

Querydsl é uma extensa estrutura Java, que ajuda a criar e executartype-safe queries in a domain specific language that is similar to SQL.

Neste artigo, exploraremos Querydsl com a Java Persistence API.

Uma observação rápida aqui é que o HQL para Hibernate foi a primeira linguagem de destino para o Querydsl, mas hoje em dia ele suporta JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections e RDFBean como back-end.

2. Preparações

Vamos primeiro adicionar as dependências necessárias em nosso projeto Maven:


    2.5.0



    com.querydsl
    querydsl-apt
    ${querydsl.version}
    provided



    com.querydsl
    querydsl-jpa
    ${querydsl.version}



    org.slf4j
    slf4j-log4j12
    1.6.1

E agora vamos configurar o plugin Maven APT:


    
    
    ...
    
        com.mysema.maven
        apt-maven-plugin
        1.1.3
        
        
            
                process
            
            
                target/generated-sources
                com.querydsl.apt.jpa.JPAAnnotationProcessor
            
        
        
    
    ...
    
    

OJPAAnnotationProcessor encontrará tipos de domínio anotados com a anotaçãojavax.persistence.Entity e gerará tipos de consulta para eles.

3. Consultas com Querydsl

As consultas são construídas com base nos tipos de consulta gerados que refletem as propriedades dos seus tipos de domínio. As invocações de função / método também são construídas de maneira totalmente segura.

Os caminhos e operações de consulta são os mesmos em todas as implementações e também as interfacesQuery têm uma interface base comum.

3.1. Uma entidade e o tipo de consulta Querydsl

Vamos primeiro definir uma entidade simples que usaremos à medida que examinarmos os exemplos:

@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 irá gerar um tipo de consulta com o nome simplesQPerson no mesmo pacote dePerson. QPerson pode ser usado como uma variável com tipo estático em consultas Querydsl como um representante para o tipoPerson.

Primeiro -QPerson tem uma variável de instância padrão que pode ser acessada como um campo estático:

QPerson person = QPerson.person;

Alternativamente, você pode definir suas próprias variáveisPerson assim:

QPerson person = new QPerson("Erich", "Gamma");

3.2. Construir consulta usandoJPAQuery

Agora podemos usar instânciasJPAQuery para nossas consultas:

JPAQuery query = new JPAQuery(entityManager);

Observe queentityManager é um JPAEntityManager.

Vamos agora recuperar todas as pessoas com o primeiro nome “Kent” como um exemplo rápido:

QPerson person = QPerson.person;
List persons = query.from(person).where(person.firstName.eq("Kent")).list(person);

A chamadafrom define a fonte da consulta e a projeção, a partewhere define o filtro elist diz ao Querydsl para retornar todos os elementos correspondentes.

Também podemos usar vários filtros:

query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));

Or:

query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));

No formato JPQL nativo, a consulta seria escrita assim:

select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"

Se você deseja combinar os filtros via "ou", use o seguinte padrão:

query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));

4. Ordenação e agregação em Querydsl

Vamos agora dar uma olhada em como a ordenação e a agregação funcionam na biblioteca Querydsl.

4.1. Encomenda

Começaremos ordenando nossos resultados em ordem decrescente pelo camposurname:

QPerson person = QPerson.person;
List persons = query.from(person)
    .where(person.firstname.eq(firstname))
    .orderBy(person.surname.desc())
    .list(person);

4.2. Agregação

Agora vamos usar uma agregação simples, pois temos algumas disponíveis (Soma, Média, Máx, Mín):

QPerson person = QPerson.person;
int maxAge = query.from(person).list(person.age.max()).get(0);

4.3. Agregação comGroupBy

A classecom.mysema.query.group.GroupBy fornece funcionalidade de agregação que podemos usar para agregar os resultados da consulta na memória.

Aqui está um exemplo rápido onde os resultados são retornados comoMap comfirstname como a chave emax age como o valor:

QPerson person = QPerson.person;
Map results =
  query.from(person).transform(
      GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));

5. Teste com Querydsl

Agora, vamos definir uma implementação do DAO usando Querydsl - e vamos definir a seguinte operação de pesquisa:

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);
}

E agora vamos construir alguns testes usando este novo DAO e vamos usar Querydsl para pesquisar por objetosPerson recém-criados (implementados na classePersonDao) e em outra agregação de teste usando a classeGroupBy é testada :

@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. Conclusão

Este tutorial ilustrou como construir o projeto JPA usando Querydsl.

Ofull implementation deste artigo pode ser encontradoin the github project - este é um projeto maven baseado em Eclipse, portanto, deve ser fácil de importar e executar como está.

Uma nota rápida aqui é - execute uma compilação simples do maven (mvn clean install) para gerar os tipos emtarget/generated-sources - e então, se você estiver usando o Eclipse - inclua a pasta como uma pasta de origem do projeto.