Tri avec Hibernate

Tri avec Hibernate

1. Vue d'ensemble

Cet article illustrehow to Sort with Hibernate, utilisant à la fois le langage de requête Hibernate (HQL) et l'API Criteria.

Lectures complémentaires:

Hibernate: sauvegarder, persister, mettre à jour, fusionner, saveOrUpdate

Un guide rapide et pratique sur les méthodes d’écriture d’Hibernate: enregistrer, conserver, mettre à jour, fusionner, enregistrerOrUpdate.

Read more

Suppression d'objets avec Hibernate

Guide rapide pour la suppression d'une entité dans Hibernate.

Read more

Intercepteurs Hibernate

Un guide rapide et pratique pour la création d'intercepteurs Hibernate.

Read more

2. Tri avec HQL

Le tri avec HQL d'Hibernate est aussi simple que d'ajouter la clauseOrder By à la chaîne de requête HQL:

String hql = "FROM Foo f ORDER BY f.name";
Query query = sess.createQuery(hql);

Une fois ce code exécuté, Hibernate générera la requête SQL suivante:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from
    FOO foo0_ order by foo0_.NAME

L'ordre de tri par défaut est croissant. C'est pourquoi la condition de commande,asc, n'est pas incluse dans la requête SQL générée.

2.1. Utilisation d'un ordre de tri explicite

Pour spécifier l’ordre de tri manuellement, vous devez inclure le sens de l’ordre dans la chaîne de requêteHQL:

String hql = "FROM Foo f ORDER BY f.name ASC";
Query query = sess.createQuery(hql);

Dans cet exemple, la définition de la clauseasc dans le HQL a été incluse dans la requête SQL générée:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_
    from FOO foo0_ order by foo0_.NAME ASC

2.2. Tri par plus d'un attribut

Plusieurs attributs, ainsi qu'un ordre de tri facultatif, peuvent être ajoutés à la clauseOrder By dans la chaîne de requête HQL:

String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
Query query = sess.createQuery(hql);

La requête SQL générée changera en conséquence:

Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_
    from FOO foo0_ order by foo0_.NAME DESC, foo0_.ID ASC

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

Par défaut, lorsque l'attribut à trier a des valeursnull, c'est au SGBDR de décider de la priorité. Ce traitement par défaut peut être remplacé en plaçanta NULLS FIRST or NULLS LAST clause in the HQL query string.

Cet exemple simple place les valeurs NULL à la fin de la liste des résultats:

String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
Query query = sess.createQuery(hql);

Voyons la clauseis null then 1 else 0 dans lesgenerated SQL query:

Hibernate: select foo0_.ID as ID1_1_, foo0_.NAME as NAME2_1_,
foo0_.BAR_ID as BAR_ID3_1_, foo0_.idx as idx4_1_ from FOO foo0_
order by case when foo0_.NAME is null then 1 else 0 end, foo0_.NAME

2.4. Trier les relations une à plusieurs

Permet d'analyser un cas de tri complexe:sorting entities in a one to many relation -Bar contenant une collection d'entitésFoo.

Nous allons le faire en annotant la collection avecthe Hibernate @OrderBy annotation; nous préciserons le champ par lequel la commande est effectuée, ainsi que la direction:

@OrderBy(clause = "NAME DESC")
Set fooList = new HashSet();

Notez que l'argumentclause de l'annotation. Ceci est propre aux@OrderBy d’Hibernate, par rapport à l’annotation JPA@OrderBy similaire. Une autre caractéristique qui différencie cette approche de son équivalent JPA est que l'argumentclause indique que le tri est effectué sur la base de la colonneNAME de la tableFOO, pas sur lename attribut deFoo.

Voyons maintenant le tri réel deBars etFoos:

String hql = "FROM Bar b ORDER BY b.id";
Query query = sess.createQuery(hql);

Leresulting SQL statement indique que lesFoo’s triés sont placés dans unfooList:

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_ID3_0_0_,
    foolist0_.ID as ID1_1_0_, foolist0_.ID as ID1_1_1_, foolist0_.NAME as
    NAME2_1_1_, foolist0_.BAR_ID as BAR_ID3_1_1_, foolist0_.idx as idx4_1_1_
    from FOO foolist0_ where foolist0_.BAR_ID=? order by foolist0_.NAME desc

Une chose à garder à l'esprit est qu'il s'agit denot possible to to sort Lists comme ce fut le cas avec JPA. La documentation d'Hibernate indique:

"Hibernate ignore actuellement @OrderBy sur @ElementCollection sur par exemple Liste . L'ordre des éléments est tel que renvoyé par la base de données, non défini. »

En remarque, il serait possible de contourner cette limitation en utilisant la configuration XML héritée pour Hibernate et en remplaçant l'élément<List..> par un élément<Bag…>.

3. Tri avec les critères Hibernate

L'API Criteria Object fournit la classeOrder comme API principale pour gérer le tri.

3.1. Définition de l'ordre de tri

La classeOrder a deux méthodes pour définir l'ordre de tri:

  • *asc*(String attribute): trie la requête parattribute dans l'ordre croissant.

  • *desc*(String attribute): trie la requête parattribute dans l'ordre décroissant.

Commençons par un exemple simple - tri par un seul attributid:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("id"));

Notez que l'argument de la méthodeasc est sensible à la casse et doit correspondre auxname de l'attribut à trier.

L'API Object de Hibernate Criteria définit explicitement une direction d'ordre de tri et cela se reflète dans l'instruction SQL générée par le code:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_
    from FOO this_ order by this_.ID sac

3.2. Tri par plus d'un attribut

Le tri par plusieurs attributs nécessite uniquement l'ajout d'un objetOrder à l'instanceCriteria, comme dans l'exemple ci-dessous:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name"));
criteria.addOrder(Order.asc("id"));

La requête générée en SQL est:

Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from
    FOO this_ order by this_.NAME asc, this_.ID sac

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

Par défaut, lorsque l'attribut à trier a des valeursnull, c'est au SGBDR de décider de la priorité. L'API Hibernate Criteria Object facilite la modification de cette valeur par défaut et desplace nulls at the end d'une liste ordonnée ascendante:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));

Voici la requête sous-jacenteSQL - avec la clauseis null then 1 else 0:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_,
    this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as
    ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when
    this_.NAME is null then 1 else 0 end, this_.NAME asc

Alternativement, nous pouvons égalementplace the nulls at the beginning d'une liste ordonnée décroissante:

Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));

La requête SQL correspondante suit - avec la clauseis null then 0 else 1:

Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_,
    this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as
    ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when
    this_.NAME is null then 0 else 1 end, this_.NAME desc

Notez que,if the attribute to sort by is a primitive type like an int, a PresisitenceException will thrown.

Par exemple, si la valeur def.anIntVariable est nulle, alors l'exécution de la requête:

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

jettera:

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException:
Null value was assigned to a property of primitive type setter of
com.cc.jpa.example.Foo.anIntVariable

4. Conclusion

Cet article explore le tri avec Hibernate - en utilisant les API disponibles pour les entités simples ainsi que pour les entités dans une relation un-à-plusieurs.

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