Tri avec JPA

Tri avec JPA

1. Vue d'ensemble

Cet article illustre les différentes manièresJPA can be used for sorting.

Lectures complémentaires:

Données de printemps JPA @Query

Apprenez à utiliser l'annotation @Query dans Spring Data JPA pour définir des requêtes personnalisées à l'aide de JPQL et de SQL natif.

Read more

Convertisseurs d'attributs JPA

Examinez le mappage des types JDBC avec les classes Java dans JPA à l'aide de convertisseurs d'attributs.

Read more

Travailler avec Kotlin et JPA

Découvrez comment utiliser JPA dans votre projet Kotlin.

Read more

2. Tri avec l'API JPA / JQL

L'utilisation de JQL pour trier se fait à l'aide de la clauseOrder By:

String jql ="Select f from Foo as f order by f.id";
Query query = entityManager.createQuery (jql);

Sur la base de cette requête, JPA génère lesSQL statement directs suivants:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.id

Notez que les mots-clés SQL de la chaîne JQL ne sont pas sensibles à la casse, mais les noms des entités et leurs attributs.

2.1. Définition de l'ordre de tri

Par défautthe sorting order is ascending, mais il peut être défini explicitement dans la chaîne JQL. Tout comme en SQL pur, les options de classement sontasc etdesc:

String jql = "Select f from Foo as f order by f.id desc";
Query sortQuery = entityManager.createQuery(jql);

Lesgenerated SQL query incluront alors le sens de la commande:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.id desc

2.2. Tri par plus d'un attribut

Pour trier par plusieurs attributs, ceux-ci sont ajoutés à la clause order by de la chaîne JQL:

String jql ="Select f from Foo as f order by f.name asc, f.id desc";
Query sortQuery = entityManager.createQuery(jql);

Les deux conditions de tri apparaîtront dans l'instructiongenerated SQL query:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc, foo0_.id desc

2.3. Définition de la priorité de tri des valeurs nulles

La priorité par défaut des valeurs nulles est spécifique à la base de données, mais elle est personnalisable via la clauseNULLS FIRST ouNULLS LAST dans la chaîne de requête HQL.

Voici un exemple simple - classer parname deFoo dans l'ordre décroissant et placerNulls à la fin:

Query sortQuery = entityManager.createQuery
    ("Select f from Foo as f order by f.name desc NULLS LAST");

La requête SQL générée inclut lesis null the 1 else 0 end clause (3e ligne):

Hibernate: select foo0_.id as id1_4_, foo0_.BAR_ID as BAR_ID2_4_,
    foo0_.bar_Id as bar_Id2_4_, foo0_.name as name3_4_,from Foo foo0_ order
    by case when foo0_.name is null then 1 else 0 end, foo0_.name desc

2.4. Trier les relations une à plusieurs

Au-delà des exemples de base, examinons maintenant un cas d'utilisation impliquantsorting entities in a one to many relation -Bar contenant une collection d'entitésFoo.

Nous voulons trier les entitésBar ainsi que leur collection d'entitésFoo - JPA est particulièrement simple pour cette tâche:

  1. Tri de la collection: ajoutez une annotationOrderBy précédant la collectionFoo dans l'entitéBar:

    @OrderBy("name ASC")
    List  fooList;
  2. Tri de l'entité contenant la collection:

    String jql = "Select b from Bar as b order by b.id";
    Query barQuery = entityManager.createQuery(jql);
    List barList = barQuery.getResultList();

Notez que l'annotation@OrderBy est facultative, mais nous l'utilisons dans ce cas car nous voulons trier la collectionFoo de chaqueBar.

Jetons un œil auxSQL query envoyés au RDMS:

Hibernate: select bar0_.id as id1_0_, bar0_.name as name2_0_ from Bar bar0_ order by bar0_.id

Hibernate:
select foolist0_.BAR_ID as BAR_ID2_0_0_, foolist0_.id as id1_4_0_,
foolist0_.id as id1_4_1_, foolist0_.BAR_ID as BAR_ID2_4_1_,
foolist0_.bar_Id as bar_Id2_4_1_, foolist0_.name as name3_4_1_
from Foo foolist0_
where foolist0_.BAR_ID=? order by foolist0_.name asc

La première requête trie l'entité parentBar. La deuxième requête est générée pour trier la collection d'entités enfantsFoo appartenant àBar.

3. Tri avec l'API d'objet de requête de critères JPA

Avec les critères JPA - la méthodeorderBy est une alternative «unique» pour définir tous les paramètres de tri: lesorder direction et lesattributes to sort par peuvent être définis. Voici l'API de la méthode:

  • orderBy (CriteriaBuilder.asc): trie par ordre croissant.

  • orderBy (CriteriaBuilder.desc): Trie par ordre décroissant.

Chaque instanceOrder est créée avec l'objet CriteriaBuilder via ses méthodesasc oudesc.

Voici un exemple rapide - tri desFoos par leursname:

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root from = criteriaQuery.from(Foo.class);
CriteriaQuery select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));

L'argument de la méthodeget est sensible à la casse, car il doit correspondre au nom de l'attribut.

Contrairement au JQL simple, l'API d'objet de requête de critères JPAforces an explicit order direction dans la requête. Remarquez dans la dernière ligne de cet extrait de code que l'objetcriteriaBuilder spécifie l'ordre de tri croissant en appelant sa méthodeasc.

Lorsque le code ci-dessus est exécuté, JPA génère la requête SQL présentée ci-dessous. JPA Criteria Object génère une instruction SQL avec une clauseasc explicite:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc

3.1. Tri par plus d'un attribut

Pour trier par plus d'un attribut, passez simplement une instanceOrder à la méthodeorderBy pour chaque attribut à trier.

Voici un exemple rapide - tri parname etid, dans l'ordreasc etdesc, respectivement:

CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root from = criteriaQuery.from(Foo.class);
CriteriaQuery select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")),
    criteriaBuilder.desc(from.get("id")));

La requête SQL correspondante est indiquée ci-dessous:

Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
    from Foo foo0_ order by foo0_.name asc, foo0_.id desc

4. Conclusion

Cet article explore les alternatives de tri de l'API Java Persistence, pour les entités simples ainsi que pour les entités dans une relation un à plusieurs. Ces approches délèguent la charge du travail de tri à la couche base de données.

L'implémentation de ce tutoriel de tri JPA se trouve dansthe GitHub project - il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.