API Filter d’Hibernate

Cette page a été rédigée il y a fort fort longtemps, et n'a pas tellement été mise à jour.

 

Vous savez, moi je ne crois pas qu'il y ait de bonne ou de mauvaise page. Moi, si je devais résumer mon wiki aujourd'hui avec vous, je dirais que c'est d'abord des rencontres. Des gens qui m'ont tendu la main, peut-être à un moment où je ne pouvais pas, où j'étais seul chez moi. Et c'est assez curieux de se dire que les hasards, les rencontres forgent une destinée... Parce que quand on a le goût de la chose, quand on a le goût de la chose bien faite, le beau geste, parfois on ne trouve pas l'interlocuteur en face je dirais, le miroir qui vous aide à avancer. Alors ça n'est pas mon cas, comme je disais là, puisque moi au contraire, j'ai pu ; et je dis merci au wiki, je lui dis merci, je chante le wiki, je danse le wiki... je ne suis qu'amour ! Et finalement, quand des gens me disent « Mais comment fais-tu pour avoir cette humanité ? », je leur réponds très simplement que c'est ce goût de l'amour, ce goût donc qui m'a poussé aujourd'hui à entreprendre une construction logicielle... mais demain qui sait ? Peut-être simplement à me mettre au service de la communauté, à faire le don, le don de soi.

Filtrer une association de type many

Hibernate donne la possibilité de filtrer des associations de type collection. Cette alternative aux requêtes HQL classiques permet notamment de contourner certains problèmes de requêtage dûs aux associations unidirectionnelles. Prenons l’exemple d’une catégorie associée à un ensemble de produits. L’association est unidirectionnelle, i.e. une catégorie "voit" les produits auxquels elle est associée, mais les produits ne "voient" pas la catégorie.

public class Categorie implements Serializable {
  private Long id;
  private String code;
  private String libelle;
  private Set<Produit> produits;

  // getters et setters
  ...
}
public class Produit implements Serializable {
  private Long id;
  private String libelle;
  private float prix;

  // getters et setters
  ...
}

Avec ce type d’association, il est impossible de lire les produits d’une catégorie via la requête HQL suivante puisque la propriété categorie n’existe pas dans la classe Produit :

 String hql = "from Produit p where p.categorie = :cat";
 Query query = session.createQuery(hql);
 List resultats = query.list(); => ECHEC

En revanche, nous pouvons utiliser un filtre de collection (méthode createFilter()) pour obtenir le résultat souhaité :

 Categorie cat = (Categorie)session.load(Categorie.class, new Long(1));
 Query  query = session.createFilter(cat.getProduits(), "");
 List<Produit> produits = query.list();
 for (Produit produit : produits) {
   System.out.println("Produit: code=" + produit.getCode() + ",titre=" + produit.getTitre());
 }

Appliquer des restrictions au filtre

Le deuxième paramètre de la méthode createFilter() permet d’ajouter des restrictions à la requête générée. Ces restrictions sont exprimées sous la forme de fragment de HQL :

 Categorie cat = (Categorie)session.load(Categorie.class, new Long(1));
 Query  query = session.createFilter(cat.getProduits(), "where this.prix > :par_prix")
                       .setFloat("par_prix", 40f);
 List<Produit> produits = query.list();
 for (Produit produit : produits) {
   System.out.println("Produit: code=" + produit.getCode() + ",titre=" + produit.getTitre());
 }

Remarque : le mot clé this permet de faire référence à l’instance de produit en cours.

La clause select

La requête peut retourner une sélection de propriétés grâce à la clause select :

 Categorie cat = (Categorie)session.load(Categorie.class, new Long(1));
 Query  query = session.createFilter(cat.getProduits(), "select this.titre where this.prix > :par_prix")
                       .setFloat("par_prix", 40f);
 List<String> titres = query.list();
 for (String titre : titres) {
   System.out.println("Titre produit: " + titre);
 }

Remarque : la clause from n’est pas nécessaire.