• Aucun résultat trouvé

Hibernate offre une API d’interrogation par critères intuitive et extensible. L’interface org.hibernate.Criteria représente une requête sur une classe persistente donnée. Hibernate fournit plusieurs critères définies

• La restriction des résultats :

Comme dans les requêtes SQL classiques, il est possible d’exprimer des conditions ou des prédicats sur les relations. List customers= sess.createCriteria(Customer.class).add( Restric- tions.like("name", "Brow%")).list() ;

• Le tri des résultats :

Le résultat d’une requête peut être trié selon un ordre à préciser moyennant ce paramètre : List

customers= sess.createCriteria(Customer.class).add( Restrictions.like("name", "F.addOrder(Order.asc("name")).list() ; • La spécification des critères sur les associations :

Il est par ailleurs possible de spécifier des critères de recherche ne portant pas sur l’objet lui

même mais sur une entité en association avec cet objet. List customers= sess.createCriteria(Customer.class) .add( Restrictions.like("name", "F%") ).createCriteria("orders").add( Restrictions.like("orderStatus", "Read%")).list() ;

• Les requêtes par l’exemple : Il est possible d’exprimer des critères sur les objets moyennant la spécification d’exemple :

Customer cust = new Customer() ; cat.setName(’Brown’) ; cat.setAdreese(’New York’) ; List results= session.createCriteria(Customer.class).add( Example.create(cust) ) .list() ;

4.3.1 Stratégies de chargement des données

Lors du mapping objet-relationnel, Hibernate va opter pour une stratégie de chargement pour la récupération des objets. Les stratégies de chargement peuvent être déclarées dans les méta-données de l’outil de mapping objet relationnel ou définies par une requête de type HQL ou une requête par critères.

Hibernate fait la distinction entre deux notions indépendantes : comment se fait le chargement d’une association (quelle requête SQL utiliser) et quand sera t elle chargée(immédiat ou tardif).

4.3.2 Mode de chargement des associations : quelle(s) requête(s) utiliser ?

Hibernate3 définit les stratégies de chargement suivantes :

Chargement par jointure : Hibernate récupère l’instance associée ou la collection dans un même select, en utilisant une jointure externe.

Exemple :Si l’on active ce mode de chargement pour tous les objets, alors l’accès à une ins- tance de l’objet Customer a pour conséquence de récupérer la collection des Orders et celles des LineItem ainsi que l’association vers l’objet Nation et celle vers Region. La requête ainsi générée ressemblerait à :

select * from Customer left outer join nation on Customer.nationKey=nation.nationKey left ou- ter join region on nation.regionKey=region.regionKey left outer join orders listorders on Custo-

mer.custKey=listorders.custKey left outer join lineitem listlineitem on listorders.orderKey=listlineitem.orderKey Chargement par select : Un second select est utilisé pour récupérer l’instance associée ou la col-

lazy="false", ce second select ne sera exécuté que lorsque vous accéderez réellement à l’as- sociation.

Exemple :Si l’on active ce mode de chargement pour la collection des Orders dans la classe Customer, alors lors de l’accès à cette collection il y aura génération de n requêtes de selection des Orders, où n est le nombre de tuples de la table customer. Les requêtes générées ressemble- raient à :

select * from Orders where Orders.custKey= ? select * from Orders where Orders.custKey= ? ...

Chargement par sous-select : Un second select est utilisé pour récupérer les associations associées aux entités récupérées dans une requête ou un chargement préalable.

Exemple : Si l’on active ce mode de chargement pour la collection des Orders dans la classe Customer, alors l’accès à cette collection donne lieu à la génération d’une requête qui ressem- blerait à :

select * from Orders where Orders.custKey in (select custKey from Customer)

Chargement par lot : Il s’agit d’une stratégie d’optimisation pour le chargement par select. Hiber- nate récupère un lot d’instances ou de collections en un seul select en spécifiant une liste de clé primaire ou de clé étrangère. La taille du lot est un paramètre à spécifier.

Exemple :Si l’on active ce mode de chargement pour la collection des Orders dans la classe Customeravec un paramètre de 5, alors lors de l’accès à cette collection il y aura génération de plusieurs requêtes (le nombre dépend de la taille de la table Customer et le paramètre du lot de chargement) qui ressemblerait à :

select * from Orders where Orders.custKey in ( ?, ?, ?, ?, ?) select * from Orders where Orders.custKey in ( ?, ?, ?, ?, ?) ...

4.3.3 A quel moment charger les associations : immédiat ou tardif ?

Hibernate fait également la distinction entre :

Chargement immédiat ou mode lazy à false : Une collection ou un attribut est chargé immédiate- ment lorsque l’objet auquel appartient cet élément (la collection ou l’attribut) est chargé. Exemple : Si l’on active ce mode de chargement au sein de l’objet Customer pour l’attribut nationet pour la collection des Orders, alors lors de l’accès à l’objet Customer l’entité Na- tionest chargée au même titre que la collection des Orders, d’où l’appellation du chargement immédiat.

Chargement tardif d’une collection ou mode lazy à true : Une collection est chargée lorsque l’ap- plication accède à une méthode sur cette collection (il s’agit du mode de chargement par défaut pour les collections).

des Orders, alors lors de l’accès à l’objet Customer, la collection des Orders n’est pas chargée. Le chargement sera effectué lors de l’invocation d’une méthode de récupération des Orders associé à l’instance courante de l’objet Customer.

Chargement "super tardif" d’une collection : Les éléments de la collection sont récupérés indivi- duellement depuis la base de données lorsque nécessaire. Hibernate essaie de ne pas charger toute la collection en mémoire que quand nécessaire (bien adapté aux très grandes collections). Exemple : Si l’on active ce mode de chargement au sein de l’objet Customer pour la collection des Orders et qu’on spécifie une colonne index, alors lors de l’accès à la collection des Orders, il est possible de charger uniquement certains éléments de la collection des Orders et non pas la totalité en utilisant l’index définit. La requête SQL ainsi produite aura la forme suivante : select * from Orders where Orders.custKey= ? and Orders.index= ?

Chargement par proxy : Dans la pratique, Hibernate charge tous les champs de la table principale et les clés étrangères sont stockées sous forme simplifiée (seul l’ID est renseigné), ce que l’on nomme un proxy. Lorsque le programme essaiera d’accéder aux membres de ce proxy, Hiber- nate générera une requête SQL et récupérera les données nécessaires afin de le remplir. Le mode de chargement par proxy concerne les associations plusieurs à un ou un à un. Une as- sociation vers un seul objet est chargée lorsqu’une méthode autre que le getter sur l’identifiant est invoquée sur l’objet associé. C’est le mode de chargement par défaut.

Exemple : Si l’on active ce mode de chargement au sein de l’objet Customer pour l’attribut Na- tion, alors l’accès à l’objet Customer n’entraînera pas le chargement de l’objet Nation associé. Chargement "sans proxy" : Une association vers un seul objet est chargée lorsque l’on accède à cet objet. Par rapport au chargement par proxy, cette approche est moins tardif (l’association est quand même chargée même si on n’accède qu’à l’identifiant). Cette approche est rarement nécessaire.

Chargement tardif des attributs : Un attribut ou un objet associé seul est chargé lorsque l’on y accède. Cette approche est rarement nécessaire.

Exemple : On peut activer le chargement tardif pour l’attribut adresse de l’objet Customer. Cet attribut ne sera pas chargé tant qu’il n’y aura pas d’accès direct à cet attribut.