Blue Flower

Chercher

1. Généralités

Les requêtes HQL et SQL Natives sont représentées par une instance d'une classe qui implémente l'interface "org.hibernate.Query". Cette interface offre des méthodes pour la liaison des paramètres, la gestion des ensembles de résultats et l'exécution des requêtes réelles. On obtient une instance d'une classe implémentant Query en utilisant la Session courante comme suit:

Query query= session.createQuery(hql);

 

Exemple d'utilisation:

String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();

La requête "hql" peut être :

  • Une clause FROM  comme ci-dessus.
  • Une clause AS, ...
  • Une clause SELECT..
  • Une clause WHERE..
  • Une clause ORDER BY..
  • Une clause GROUP BY......

......

1.1. Interface org.hibernate.Query

C'est la représentation objet d'une requête Hibernate. L'ordre peut comporter des paramètres nommés, (par exemple :nom). Un même paramètre peut apparaître plusieurs fois dans la requête. On peut aussi utiliser le "?" pour un paramètre comme en JDBC, tout en sachant qu' ils sont numérotés à partir de 0 contrairement à JDBC. Toutefois on ne peut pas mélanger les deux notations de paramètre (celle de JBC et celle de Hibernate). La durée de vie d'une requête est limitée à celle de la Session qui l'a créée. les  principales méthodes de l'interface "org.hibernate.Query"  sont:

  1. - executeUpdate() exécute l'instruction update ou delete
  2. - List list() renvoie le résultat d'une requête comme une liste, si plusieurs entités par ligne l'élément de liste est un Object[]
  3. - Object uniqueResult() pour récupérer l'unique résultat d'une requête ; null si aucun résultat et exception NonUniqueResultException si plus d'un résultat.
  4. - Query setInteger (int position, int val)
  5. - Query setInteger (String name, int val)
  6. - Query setString (int position, String val)
  7. - Query setString (String name, String val)

1.2. Interface org.hibernate.SQLQuery

L'interface SQLQuery dérive de l'interface Query; on se sert de SQLQuery pour construire des requêtes sql. L'execution de requêtes natives est contrôlée par l'interface SQLQuery; ccelui est obtenu e nfaisant appel à à la méthode Session.createSQLQuery(). The following sections describe how to use this API for querying.

.....


II. Le langage HQL

1. Généralités

HQL (Hibernate Query Langage) est un langage d'interrogation des classes persistantes avec une syntaxe proche du SQL. Cependant les objets manipulés sont les classes et membres du mapping ce qui n'est pas le cas pour SQL qui réalise les requêtes directement sur la base de données. HQL génére la requête sql et l'exécute sur la BD concernée par l'application de faîon transparente . HQL contient des fonctionnalités spécifiques au modèle objet.
HQL supporte le Polymorphisme, le mapping des Associations, et il est beaucoup moins verbeux que le SQL. Pour interroger les classe persistantes ( envoyer des requêtes sql) en plus de SQL Natives ou HQL , on se sert de l' API Criteria (voir QBC ( Query By Criteria) et QBE( Query By Example)) .

Pourquoi utiliser HQL ?

  1. - HQL prend en compte toutes les opérations relatives aux requêtes sql classiques.
  2. - Les requêtes HQL returnent des objets et ainsi on dispose d'une facilité d'utilisation. Cela élimine le faite qu'on soit obligé de créer l'objet qu'on veut utiliser et de remplir un à un les champs correspondant aux données à utiliser.
  3. - HQL supporte aussi les requêtes appliquées sur des objets se trouvant dans un environnement où on a des classes obéissant au polymorphisme (Polymorphic Queries).
  4. - Supporte des propriétész avancées de sql comme la pagination, "fetch join" avec des profile dynamiques, Inner/outer/full joins et le produit cartésien .
  5. - Hibernate supporte aussi les fonctions d'aggragation comme (max, avg), le regroupement (GROUP BY), ORDER BY, les sous-requêtes et les appels de fonctions (voir procédurs stockées).

2- Syntaxe du langage HQL

Les requêtes HQL sont de trois sortes:

  • Clauses
  • Fonctions d'aggrégations
  • Sous-requêts

2.1. Clauses :
2.1.2. FROM :
C'est la clause la plus simple utilisée par HQL; elle spécifie l'objet qui sera retourné comme résultat de la requête; cette clause est utilisée presque toujours avec la clause select:
syntaxe :
from object [as object_alias]* object_alias (<-- une alias ). from comp.Dept as dept
Cette requête retournera toutes les instances de l'objet dept .
2.1.3.  select :
Elle spécfie des objets et des propriétés qui seront retournés comme résultat de la reqête; en général elle s'utilise avec la clause from .
syntaxe :
select [object.]property

select dept.mgr from comp.Dept as dept

Retournera toutes les valeurs de mrg de toutes les instances de l'objet dept.

2.1.4. where :
Précise une ou des conditions à satisfaire pour les résultat retournés.Cette clause s'utilise en général avec les clauses select et/ou from.
syntaxe :
where condition
Ici les ou la condition est une combinaison des opérateurs logiques =, >, AND, NOT etc.

select dept.mgr from comp.Dept as dept where dept.emp_no > 10
Will return all instances of mgr in dept whose corresponding emp_no values are greater than 10.

2.1.5. order by :
La liste retounée par la requête peut être triée par n'importe quelle propriété de la classe ou du composant retourné; cett clause est utiliséé avec les clauses select et from .
syntaxe :
order by object0.property0 [asc|desc][, object1.property0]...
Par défaut l'ordre est ascendant .

select dept.mgr from comp.Dept as dept order by dept.emp_no asc
Cette requête retourne une liste de toutes les valeurs de dept.mgr des instances de l'objet dept ordonnées suivant les valeurs ascendantes de dept.emp_no

2.1.6. group by :
Si la requête retourne des valeurs aggrégées, celles ci peuvent être groupées par propriété ou composant.
syntaxe :
group by object0.property0[, object1.property0]...

select dept.emp_no from comp.Dept as dept group by dept.mgr
Cette requête retourne une liste de toutes les valeurs des propriétés dept.emp_no des instances de dept en les regroupant suivant les valeurs des dept.mgr

2.2. Fonctions d'aggrégations
Les requêtes HQL peuvent aussi retourner le résultat de fonctions d'aggrégation (comme sum, average, et count) sur les propriétés de tous les objets satisfaisant d'autres critéres dans la requête; Voici une liste des fonctions d'aggrégation avec leur syntaxe:

  1. - count( [ distinct | all ] object | object.property )
  2. - count(*) (équivalent à count(all ...), compte les valeurs nulles aussi)
  3. - sum ( [ distinct | all ] object.property)
  4. - avg( [ distinct | all ] object.property)
  5. - max( [ distinct | all ] object.property)
  6. - min( [ distinct | all ] object.property)

2.3. Sous-requêtes
Pour les bases de données supportant les sous-requêtes, Hibernate supporte les sous-requêtes dans les requêtes. Une sous-requête doit être entre parenthèses (souvent pour un appel à une fonction d'agrégation SQL). Même les sous requêtes corrélées (celles qui font référence à un alias de la requête principale) sont supportées.
Notez que les sous-requêtes HQL peuvent arriver seulememnt dans les clauses select ou where.

3. Quelques exemples

3.1 Exemple d'utilisation:

Query query = session.createQuery("insert into Stock(stock_code, stock_name)" +
    			"select stock_code, stock_name from backup_stock");
int result = query.executeUpdate();

La méthode  query.executeUpdate() retournera le nombre d'enregistrement enserré, mis à jour ou détruits .

.........

 


Interface org.hibernate.Criteria

Criteria est une interface dérivant de CriteriaSpecification. Criteria est un API simplifié permettant de recouvrir à partir de BD, des données contenant ou composées d'objets en se basant sur des critères; cette fonctionnalité convient pour une recherche avec plusieurs conditions. Une instance Session avec sa méthode createCriteria() permet de créer une ou des instance de Criteria ; Session est en l’occurrence une Fabrique de Critria.
Cette méthode a comme paramètre le nom de la classe mappée sur laquelle on va lancer la requête et en voici une exemple:
Criteria criteria= session.createCriteria(Order.class);
Cette instruction retournent une instance de la classe Criteria pour la classe mappée Order.
Chaque classe de l'API Criteria représente un aspect de l'approche relationel et l' API Criteria a cinq parties qui sont souvent utilisée :

  1. Criteria
  2. Criterion
  3. Restrictions
  4. Projection
  5. Order

Les critères de recherche utilisables dans des requêtes sql ont une représentation orientée objet en l'interface Criterion. En d'autres termes, l'interface Criterion est la représentation orientée objet de la clause "where" dans une requête sql classique et La classe "org.hibernate.criterion.Restrictions" définit des méthodes de type de Criterion (critère de recherche) pré-définis. (voir interfaces Criterion et Restrictions).
Exemple :

Criteria criteria= session.createCriteria(Order.class);
Criterion crit=Restriction.eq("orderId","OD00009");
criteria.add(crit);

Cet exemple introduit avec Criterion la clause "where" qui, losqu'elle est ajoutée à l'objet Criteria , offre une requête complète avec des restrictions ; ceci est fait à travers la méthode "org.hibernate.criterion.Restrictions.eq()";

la classe org.hibernate.criterion.Restrictions :
La classe Restrictions est essentiellement une fabrique d'instances de classe Criterion dont toutes les méthodes sont "static". Cette classe Restrictions fournit presque toutes les méthodes permettant d"implémenter des restrictions que l'on peut introduire via la clause "where" d'une requête sql classique; ces méthodes sont:
(eq()), (and()),(like()) etc...

la classe org.hibernate.criterion.Projection :
La classe Projection est une représentation orientée objet de l'ensemble des résulats d'une projection au sens d'une requête sql; une projection, au sens d'une requête sql classique, est une instruction sql permettant de sélectionner un ensemble de colonnes dans une table; ce sont donc les champs qui se trouvent après la clause select d'une requête sql. La classe Projection permet de faire une projection au sens d'une requête sql; pour cela, on se sert de la méthode addProjection() de la classe ProjectionList. La méthode addProjection() de la classe Creiteria retourne un objet Criterion comme le montre l'exemple suivant:

List orders = session.createCriteria(Order.class)
     .setProjection( Projections.projectionList()
      .add( Projections.rowCount())).list();

Ci-dessus on illustre quelques utilisations de la projection :
Prenons la requête sql simple suivante:
SELECT * FROM ORDER
Cette requête est une projection qui liste tous les éléments de la table ORDER; on peut facilement se servir des classes de l' API Criteria pour réaliser cette requête:
List orders= session.createCriteria(Order.class).list();
Et pour des raisons de simplicité et de clarté on peut décomposer cette instruction en deux instructions très simples comme suit:

Criteria criteria= session.createCriteria(Order.class);  
List orders=criteria.list();

Ensemble les deux instructions ci-dessus permettent de retirer de la BD les èlèments permettant de remplir les champs de l'objet mappè Order, les rangent dans une liste et retourne la liste sous forme d'objet.
Si on avait à retirer un élément, on utiliserait la reqête sql
SELECT NAME FROM PRODUCT
et on procéderait avec l'approche objet comme suit :

List products=session.createCriteria(Product.class)
     . setProjection(Projection.property(\"name\"))
     .list();

Il est claire que le champ présent dans la clause clause SELECT sert de paramètre à la méthode Projection.property(); le reste de l'instruction est la construction de la liste que l'on va avoir en sortie en effet session.createCriteria a comme paramètre la classe mappée sur laquelle on va travailler, setProjection recupére toute les instances contenant "name" et list() construit la liste de tous les résultats.
Si on a plus d'une colonne dans la clause SELECT
SELECT NAME, ID FROM PRODUCT
on se sert de la methode add() pour ajouter chaque champ conserné et cela donne avec QBC :

List products =session.createCriteria(Product.class).setProjection(
    Projections.propertyList()
        .add(Projection.property(\"name\"))
        .add(Projection.property(\"id\"))
    )
    .list();

Si on réalise des requêtes complexes contenant des Joins comme suit:
SELECT O.*, P.* FROM ORDERS O, PRODUCT P WHERE O.ORDER_ID=P.ORDER_ID;
Cela se traduit facilement avec QBC :

List orders = session.createCriteria(Order.class)
            .setFetchMode("products",FetchMode.JOIN)
            .list();

C'est aussi simple que ça en se servant de la méthode setFetchMode() de Criteria. Exemples de Projection suivie de restrictions
Pour faire une projection d'un certain nombre de colonnes de la BD avec un cetain nombre de condition on se sert de la classe Restriction; toute les condition de retriction utilisables danss une requête sql sont utilisables aussi dans QBC et les plus souvent utilisée sont:

Restriction.between cettte méthode utilisée pour introduire une contrainte comme dans sql
Restriction.eq cettte méthode utilisée pour introduire une contrainte comme dans sql.
Restriction.ge cettte méthode utilisée pour introduire une contrainte comme dans sql.
Restriction.gt cettte méthode utilisée pour introduire une contrainte comme dans sql.
Restriction.idEq is used to apply an "equal" constraint to the identifier property.
Restriction.in is used to apply an "in" constraint to the field.
Restriction.isNotNull is used to apply an "is not null" constraint to the field.  
Restriction.isNull is used to apply an "is null" constraint to the field.
Restriction.ne is used to apply a "not equal" constraint to the field.   

Donc une requête sql comme :
SELECT * FROM ORDERS WHERE ORDER_ID="1092";
se traduit comme

   List orders= session.createCriteria(Order.class)
               .add(Restrictions.eq("orderId","1092"))
               .list();

Appliquez des contrainte est aussi simple que ça; on peut l'illuustrer encore par l'exemple ci-dessus:

   SELECT O.*, P.* FROM ORDERS O, PRODUCT P WHERE
    O.ORDER_ID=P.ORDER_ID AND P.ID="1111";

que l'on traduit en utilisant QBC comme suit:

List orders = session.createCriteria(Order.class)
        .setFetchMode("products",FetchMode.JOIN)
        .add(Restrictions.eq("id","1111"))
        .list();
 

En ajoutant la restriction en se servant de lamethode setFetchMode() on obtient la même chose que ci-dessus;

List orders = session.createCriteria(Order.class)
     .setProjection( Projections.projectionList()
     .add( Projections.count("id") ))
     .list();
 

De la même manière les fonction d'aggrégation sont utilisées comme Projections.count() dans l'exemple ci-dessus; chaque fonction d'aggrégation utilisée a comme argument le nom de la colonne concernée ( ici c'est 'id' pour la fonction count) et le résultat est donné en l eregroupant selon certaines conditions relative è cerataines colonnes; pour cela on se sert de la méthode Projections.groupProperty() ; comme exemple considérons la requête suivant:

SELECT COUNT(ID) FROM ORDER HAVING PRICETOTAL>2000 GROUP BY ID
On a la même chose si on utilise QBC comme suit:

List orders = session.createCriteria(Order.class)
     .setProjection( Projections.projectionList()
      .add( Projections.count("id") )
       .add( Projections.groupProperty("id") )
     )
      .list(); 
 

la classe org.hibernate.criterion.Order :
LA classe Order représente la clause "order by de sql. Dans la suite on va voir comment on se sert de ces classes pour se passer des Sql Natif ou HSQL dans les cas où c'est possible .
QBC (Query By Criteria)
C'est vraiment avec QBC que Hibernate s'utilise en se passant complétement des requêtes Sql; ces dernières sont gérées de faîon transparente par l' API; le développeur se sert uniquement d'objets comme l'ilustre l'exemple ci-dessus:
Exemple :

 Criteria criteria = session.createCriteria(Order.class);
 criteria.add( Expression.eq("id", "I009") );
 List result = criteria.list();

On voit qu'on obtient un instance de la classe Criteria par la méthode session..createCriteria qui a comme paramètre le nom de la classe mappée au lieu d' une requête et puis les critères sont ajoutée via la méthode criteria.add() qui prend comme paramètre ce que retourne la méthode Expression.eq().

QBE (Query By Example)
Cette approche n'est très différente de l'utilisation de QBC; en se servant de QBC on sert de la partie rerstriction de la clause where tandisque avec QBE de la partie exemple de la resrtction; cette partie exemle est introduite par par " as like 'I%'" sachant qu' ici on s'interesse aux valeurs commenîant par 'I'. L'idée principale de QBE est que l'application offre une instance de la calsse sur laquelle on lance la requête avec la valeur de la propriété set pour toute valeur par default. .
Example :

   User exampleUser = new User();
   exampleUser.setFirstname("Max");
  Criteria criteria = session.createCriteria(User.class);
  criteria.add( Example.create(exampleUser) );
  List result = criteria.list();

Cette instruction retourne tous les objets persistants contenant le champ Firstname qui a comme valeur "Max".

précédent suivant