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.