Un guide sur Querydsl avec JPA

Un guide de Querydsl avec JPA

1. Vue d'ensemble

Querydsl est un framework Java complet, qui permet de créer et d'exécutertype-safe queries in a domain specific language that is similar to SQL.

Dans cet article, nous allons explorer Querydsl avec l'API Java Persistence.

Il convient de noter que HQL pour Hibernate était le premier langage cible de Querydsl, mais qu’il prend désormais en charge JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections et RDFBean.

2. Les préparatifs

Ajoutons d'abord les dépendances nécessaires dans notre projet Maven:


    2.5.0



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



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



    org.slf4j
    slf4j-log4j12
    1.6.1

Et maintenant, configurons le plugin Maven APT:


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

LesJPAAnnotationProcessor trouveront les types de domaine annotés avec l'annotationjavax.persistence.Entity et génèrent des types de requêtes pour eux.

3. Requêtes avec Querydsl

Les requêtes sont construites en fonction des types de requête générés qui reflètent les propriétés de vos types de domaine. Les appels de fonction / méthode sont également construits de manière totalement sécurisée.

Les chemins de requête et les opérations sont les mêmes dans toutes les implémentations et les interfacesQuery ont également une interface de base commune.

3.1. Une entité et le type de requête Querydsl

Définissons d'abord une entité simple que nous allons utiliser au fil des exemples:

@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 générera un type de requête avec le nom simpleQPerson dans le même package quePerson. QPerson peut être utilisé comme variable de type statique dans les requêtes Querydsl en tant que représentant du typePerson.

Premièrement -QPerson a une variable d'instance par défaut accessible sous forme de champ statique:

QPerson person = QPerson.person;

Vous pouvez également définir vos propres variablesPerson comme ceci:

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

3.2. Créer une requête en utilisantJPAQuery

Nous pouvons maintenant utiliser les instancesJPAQuery pour nos requêtes:

JPAQuery query = new JPAQuery(entityManager);

Notez que leentityManager est un JPAEntityManager.

Récupérons maintenant toutes les personnes portant le prénom «Kent» comme exemple rapide:

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

L'appelfrom définit la source de la requête et la projection, la partiewhere définit le filtre etlist indique à Querydsl de renvoyer tous les éléments correspondants.

Nous pouvons également utiliser plusieurs filtres:

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

En JPQL natif de la requête s’écrirait comme ceci:

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

Si vous souhaitez combiner les filtres via “ou”, utilisez le modèle suivant:

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

4. Classement et agrégation dans Querydsl

Voyons maintenant comment le classement et l'agrégation fonctionnent dans la bibliothèque Querydsl.

4.1. Commande

Nous allons commencer par classer nos résultats par ordre décroissant par le champsurname:

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

4.2. Agrégation

Utilisons maintenant une simple agrégation, car nous en avons quelques-unes disponibles (Sum, Avg, Max, Min):

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

4.3. Agrégation avecGroupBy

La classecom.mysema.query.group.GroupBy fournit une fonctionnalité d'agrégation que nous pouvons utiliser pour agréger les résultats de requête en mémoire.

Voici un exemple rapide où le résultat est renvoyé sous la formeMap avecfirstname comme clé etmax age comme valeur:

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

5. Tester avec Querydsl

Maintenant, définissons une implémentation DAO à l'aide de Querydsl - et définissons l'opération de recherche suivante:

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

Et maintenant, construisons quelques tests en utilisant ce nouveau DAO et utilisons Querydsl pour rechercher les objetsPerson nouvellement créés (implémentés dans la classePersonDao) et dans une autre agrégation de test en utilisant la classeGroupBy est testée :

@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. Conclusion

Ce tutoriel explique comment construire un projet JPA à l'aide de Querydsl.

Lesfull implementation de cet article peuvent être trouvésin the github project - il s'agit d'un projet maven basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.

Une remarque rapide ici est: exécutez une simple compilation maven (mvn clean install) pour générer les types danstarget/generated-sources - puis, si vous utilisez Eclipse, incluez le dossier comme dossier source du projet.