1 
Développement des 
composants web 
Persistance avec Hibernate 
(Auteur : Pr BOUZIDI Issam)
2 
Présentation JDBC 
 JDBC est l'acronyme de Java DataBase 
Connectivity et désigne une API définie par 
Sun pour permet...
3 
Les outils nécessaires pour 
utiliser JDBC 
 Pour pouvoir utiliser JDBC, il faut un pilote qui est 
spécifique à la ba...
Etapes dans une transaction d’accès 
4 
aux données JDBC 
 1. Chargement du pilote JDBC 
 2. Connexion 
 3. Exécution d...
5 
Pilotes JDBC: Chargement 
 Pour se connecter à une base de données, il faut tout 
d'abord charger le pilote. 
• la doc...
L'établissement de la connexion 
6 
 Pour se connecter à une base de données, il faut 
instancier un objet de la classe C...
7 
L'exécution de requêtes SQL 
 Une fois la connexion établie, il est possible 
d'exécuter des ordres SQL 
 Les classes...
L'exécution des requêtes SQL 
 Les requêtes d'interrogation SQL sont exécutées avec les méthodes 
d'un objet de la classe...
L'exécution des requêtes SQL 
 Pour une requête de type interrogation (SELECT), la méthode à utiliser de la classe 
9 
St...
10 
Traitement des résultats 
 La classe ResultSet : C'est une classe qui représente une 
abstraction d'une table qui se ...
11 
Traitement des résultats 
 La méthode getMetaData() retourne un objet de la classe 
ResultSetMetaData qui permet d'ob...
12 
Traitement des résultats 
 Exemple : 
 //parcours des données retournées 
 try { 
ResultSetMetaData rsmd = résultat...
13 
Traitement des résultats 
 Les méthodes getXXX() permettent d'extraire les 
données selon leur type spécifiée par XXX...
14 
L'utilisation des transactions 
 Définition : Une transaction permet de ne valider un ensemble de 
traitements sur la...
15 
L'utilisation des transactions 
 Une fois le mode auto-commit désactivé, appel à la 
méthode commit() de la classe Co...
16 
Hibernate : chapitres 
1. Présentation framework Hibernate 
2. Éléments de base 
• Beans 
• Fichier de mapping (fichie...
17 
Hibernate: chapitres 
10. Langage de requête (HQL)  requête complexe 
11. Fonctions avancées (pagination, itération,....
18 
Présentation Hibernate 
 Hibernate a besoin de plusieurs éléments pour 
fonctionner : 
• une classe de type javabean ...
19 
Présentation Hibernate 
 Hibernate a besoin de plusieurs éléments pour 
fonctionner : 
• une classe de type javabean ...
20 
Présentation Hibernate 
Application 
Classes encapsulant les données 
Hibernate 
Base de données 
Fichier de mapping 
...
21 
Création du Bean 
 Cette classe doit respecter le standard des 
javabeans notamment encapsuler les 
propriétés dans d...
22 
Création du Bean 
public class Personne { 
private long identifiant; 
private String nom; 
private String prenom; 
pub...
Création du fichier de mapping 
 Pour assurer le mapping, Hibernate a besoin d'un fichier 
de correspondance (mapping fil...
Création du fichier de mapping 
24 
(suite) 
 Le fichier débute par un prologue et une définition de la 
DTD utilisée par...
Création du fichier de mapping 
25 
(suite) 
Exemple : 
<hibernate-mapping> 
<class name="modele.Commande" table="COMMANDE...
Création du fichier de mapping 
26 
(suite) 
 Le tag <class> permet de préciser des informations sur 
la classe qui va en...
Création d'un fichier de mapping 
27 
(suite) 
 Le tag enfant <id> du tag <class> permet de fournir des 
informations sur...
Création du fichier de mapping 
28 
(suite) 
 Exemple de types de génération fournies en 
standard par Hibernate (possède...
Création du fichier de mapping 
29 
(suite) 
 Le tag <property>, fils du tag <class>, permet de fournir des 
informations...
30 
Fichier de configuration 
 Pour exécuter Hibernate, il faut lui fournir un certain 
nombre de propriétés concernant s...
Fichier de configuration (suite) 
31 
 Les principales propriétés pour configurer la connexion JDBC sont : 
• hibernate.c...
Fichier de configuration (suite) 
32 
Exemple : 
<hibernate-configuration> 
<session-factory> 
<property name="hibernate.c...
33 
Structure de notre 
application Hibernate
34 
Utilisation d'Hibernate 
 Pour utiliser Hibernate dans le code, il est nécessaire de 
réaliser plusieurs opérations :...
35 
Utilisation d'Hibernate 
 Par défaut, la méthode openSession() qui va 
ouvrir une connexion vers la base de données 
...
36 
Persistance d'une nouvelle 
instance 
 Pour créer une nouvelle occurrence dans la source de 
données, il suffit de cr...
37 
Persistance d'une nouvelle 
instance 
public static void main(String args[]) throws Exception { 
Configuration config ...
Obtenir une instance à partir de 
38 
son identifiant 
 La méthode load() de la classe Session permet 
d'obtenir une inst...
Obtenir une instance à partir de 
39 
son identifiant (suite) 
public static void main(String args[]) throws Exception { 
...
40 
Modifier une instance 
 Pour mettre à jour une occurrence dans la 
source de données, il suffit d'appeler la 
méthode...
41 
Modifier une instance (suite) 
Transaction tx = null; 
try { 
tx = session.beginTransaction(); 
Commande commande = (C...
42 
Supprimer une instance 
Transaction tx = null; 
try { 
tx = session.beginTransaction(); 
Commande commande = (Commande...
43 
Le langage de requête HQL 
 Pour offrir un langage d'interrogation commun à 
toute les bases de données, Hibernate pr...
44 
Clause from 
 La requête Hibernate la plus simple est de la 
forme : 
• from Commande c where c.code='code1' and 
c.l...
45 
Clause from 
try { 
Query query = session.createQuery("from Commande where 
code='code1'"); 
List commandes = query.li...
46 
Passage des paramètres 
 D’autres exemples pour écrire des 
requêtes HQL : 
• Query query1 = session.createQuery( 
"f...
47 
Clause « select » 
 La clause select sélectionne les objets et 
propriétés qui doivent être retournés dans le 
résult...
48 
Fonctions d'agrégation 
 Les requêtes HQL peuvent aussi retourner le résultat de 
fonctions d'agrégation sur les prop...
49 
Clause « order by » 
 La liste retournée par la requête peut être triée par n'importe 
quelle propriété de la classe ...
50 
Le langage de requête HQL 
(suite) 
 Exercice : 
Utiliser une requête HQL et la méthode 
delete de la classe Session ...
51 
Les relations 
 Un des fondements du modèle de données relationnelles 
repose sur les relations qui peuvent interveni...
Relation de type one-to-many 
 La relation de type one-to-many est définie 
quand une classe contient une liste ou une 
c...
Relation de type one-to-many 
 Pour mapper une relation one-to-many on doit suivre les 
53 
opérations suivantes : 
1. Cr...
Relation de type one-to-many 
54 
Exemple : 
<class name="modele.Client" table="CLIENT" > 
<id name="identifiant" type="lo...
Relation de type one-to-many 
 Dans la classe de persistance ajouter les instructions 
55 
suivantes : 
1. Ouvrez une tra...
Relation de type one-to-many 
 Le code qui correspond aux instructions précédentes : 
tx = session.beginTransaction(); 
C...
Relation de type one-to-many 
57 
 En utilisant le mapping one-to-many la 
récupération d’un objet père permet la 
récupé...
Relation de type one-to-many 
58 
 Création en cascade : hibernate permet de faire la 
création dans une relation one-to-...
Relation de type one-to-many 
 Comme pour la création nous pouvons aussi 
faire la suppression en cascade. Mais il va 
fa...
Relation de type one-to-many 
60 
Exercice : 
 Utiliser l’option cascade pour : 
• Créer et persister automatiquement un ...
Relation de type one-to-many 
61 
Exemple de suppression en cascade : 
tx = session.beginTransaction(); 
Client client = (...
62 
Tri des collections 
 Hibernate donne la possibilité de trier une 
collection récupérée directement à partir d’un 
ob...
63 
Initialisation tardive 
Optimisation du cache 
 Hibernate donne également la possibilité de ne charger des objets au ...
64 
Relation de type many-to-one 
 La relation many-to-one est l’opération inverse de la 
relation one-many-to. 
 La rel...
65 
Relation de type many-to-one 
 Pour mapper une relation many-to-one, par 
rapport à l’exemple précédent, suivre les 
...
66 
Relation de type many-to-one 
 Exemple : 
<class name="modele.Commande" table="COMMANDE"> 
<id name="identifiant" typ...
67 
Relation de type many-to-one 
 Dans la classe de persistance ajouter les instructions 
suivantes : 
1. Ouvrez une tra...
68 
Relation de type many-to-one 
 Le code qui correspond aux instructions 
précédentes : 
tx = session.beginTransaction(...
69 
Relation de type many-to-one 
 En utilisant le mapping many-to-one la 
récupération d’un objet fils permet la 
récupé...
Relation de type many-to-many 
 Pour mapper une relation many-to-many, en se basant sur un exemple 
70 
(Client, Fourniss...
Relation de type many-to-many 
71 
 Exemple : 
<class name="modele.Client" table="CLIENT" > 
<id name="identifiant" type=...
Relation de type many-to-many 
 Le code qui correspond aux 
instructions précédentes : 
Client client = new Client("chafi...
Relation de type many-to-many 
 Si la table de relation contient des champs supplémentaires, nous 
73 
devons passer par ...
Relation de type many-to-many 
 Exercice : utilisation d’une table de 
relation qui contient un attribut 
supplémentaire....
Relation de type many-to-many 
75 
 Correction : 
tx = session.beginTransaction(); 
Client client = (Client) session.get(...
76 
Relation de type one-to-one 
 Une association one-to-one vers une 
autre classe persistante est déclarée en 
utilisan...
77 
Relation de type one-to-one 
Associations sur clé primaire 
 Les associations sur clé primaire ne nécessitent pas de ...
78 
Relation de type one-to-one 
Associations sur clé primaire 
 Supposons dans cet exemple que nous avons une relation o...
79 
Relation de type one-to-one 
Associations sur clé primaire 
 Assurez vous que les clés primaires des 
lignes associée...
80 
Relation de type one-to-one 
Associations sur clé primaire 
<class name="modele.Client" table="CLIENT"> 
<id name="ide...
81 
Relation de type one-to-one 
Associations sur clé primaire 
<class name="modele.Societe" table="SOCIETE"> 
<id name="i...
82 
Relation de type one-to-one 
Associations sur clé étrangère 
 Une clé étrangère avec une contrainte d'unicité, de 
So...
83 
Relation de type one-to-one 
Associations sur clé étrangère 
<class name="modele.Client" table="CLIENT"> 
<id name="id...
84 
Relation de type one-to-one 
Associations sur clé étrangère 
<class name="modele.Societe" table="SOCIETE"> 
<id name="...
85 
Requête HQL (jointure) 
 Comme nous pouvons faire des requêtes 
simple avec le langage HQL, nous pouvons 
également f...
86 
Requête HQL (jointure) 
 La liste résultat de la requête doit retourner une collection de 
tableau. 
 Chaque tableau...
87 
Clause « select » 
 La clause select sélectionne les objets et 
propriétés qui doivent être retournés 
dans le résult...
88 
Fonctions d'agrégation 
 Les requêtes HQL peuvent aussi retourner le résultat de 
fonctions d'agrégation sur les prop...
89 
Fonctions d'agrégation 
 Pour sélectionner la commande qui a le montant le plus élevé, 
nous pouvons utiliser la requ...
90 
Fonctions d'agrégation 
 Exercice : 
 Utiliser le langage HQL pour récupérer, pour 
chaque client, la somme des mont...
91 
Fonctions d'agrégation 
 Correction : 
Query query7 = session.createQuery("select sum(cmd.montant), cl.nom 
from Comm...
92 
Clause « order by » 
 La liste retournée par la requête peut être triée par n'importe 
quelle propriété de la classe ...
93 
Héritage 
 Hibernate permet de faire aussi le mapping de 
l’héritage. 
 Hibernate supporte trois stratégie d’héritag...
94 
Héritage 
 Pour implémenter le mapping de l’héritage il 
faut suivre les étapes suivantes : 
1. Ajouter une hiérarchi...
95 
Héritage 
<class name="modele.Personne" table="PERSONNE"> 
<id name="identifiant" type="long" column="IDENTIFIANT"> 
<...
96 
Héritage 
 Exercice : 
 Créer et mapper les classe suivantes : 
• Personne 
• Employe 
• Etudiant 
 Les classes Emp...
97 
Héritage 
 Correction 
tx = session.beginTransaction(); 
Etudiant etudiant= new Etudiant("chafiq", 
"bouzidi","adress...
98 
Héritage 
 Implémentation de l’héritage : une table par classe fille. 
Pour implémenter le mapping de l’héritage il f...
99 
Héritage 
<class name="modele.Personne" table="PERSONNE"> 
<id name="identifiant" type="long" column="IDENTIFIANT"> 
<...
100 
Externaliser des requêtes 
nommées 
 Vous pouvez aussi définir des requêtes 
nommées dans le document de 
mapping. 
...
101 
Externaliser des requêtes 
nommées 
<query name="PersonneByNomEtPrenom"> 
<![CDATA[from Personne where nom like ? and...
102 
Pagination 
 Si vous avez besoin de spécifier des liens sur votre 
ensemble de résultats (le nombre maximum de ligne...
103 
Itération "scrollable" 
 Si votre connecteur JDBC supporte les 
ResultSet s "scrollables", l'interface 
Query peut ê...
104 
Itération "scrollable" 
Query query = session.createQuery("select prenom, 
nom from Personne order by prenom"); 
Scro...
105 
Requêtes en SQL native 
 Vous pouvez construire votre requête en SQL, en utilisant 
createSQLQuery(). 
 Il est néce...
106 
Requêtes en SQL native : 
requête d’entités 
 Les requêtes précédentes ne retournaient que des valeurs scalaires, 
e...
107 
Requêtes par critères 
 HQL est extrêmement puissant, mais 
certains développeurs préfèrent 
construire des requêtes...
108 
Requêtes par critères 
(Restriction du résultat) 
Criteria criteria =session.createCriteria(Personne.class). 
add(Res...
109 
Requêtes par critères 
(Trier les résultats) 
 Vous pouvez trier les résultats en 
utilisant org.hibernate.criterion...
110 
Requêtes par critères 
(Association) 
 Vous pouvez facilement spécifier des 
contraintes sur des entités liées, par ...
Synchronisation du cache avec 
111 
la base : méthode flush 
 Les instances transactionnelles persistantes 
(objets charg...
Synchronisation du cache avec 
112 
la base : méthode flush 
Exemple : 
try { 
Session session = sessionFactory.openSessio...
Prochain SlideShare
Chargement dans…5
×

Jdbc hibernate

1 208 vues

Publié le

0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
1 208
Sur SlideShare
0
Issues des intégrations
0
Intégrations
6
Actions
Partages
0
Téléchargements
105
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Jdbc hibernate

  1. 1. 1 Développement des composants web Persistance avec Hibernate (Auteur : Pr BOUZIDI Issam)
  2. 2. 2 Présentation JDBC  JDBC est l'acronyme de Java DataBase Connectivity et désigne une API définie par Sun pour permettre un accès aux bases de données avec Java.  Les classes de JDBC sont regroupées dans le package java.sql et sont incluses dans le JDK à partir de sa version 1.1.
  3. 3. 3 Les outils nécessaires pour utiliser JDBC  Pour pouvoir utiliser JDBC, il faut un pilote qui est spécifique à la base de données à laquelle on veut accéder.  Ce pilote permet de réaliser l'indépendance de JDBC vis à vis des bases de données.  Les drivers se présentent souvent sous forme de fichiers jar dont le chemin doit être ajouté au classpath pour permettre au programme de l'utiliser.  Sun maintient une liste des drivers jdbc à l'url : http://www.javasoft.com/products/jdbc/drivers.html
  4. 4. Etapes dans une transaction d’accès 4 aux données JDBC  1. Chargement du pilote JDBC  2. Connexion  3. Exécution de la requête  4. Traitement des résultats  5. Fermeture de la connexion
  5. 5. 5 Pilotes JDBC: Chargement  Pour se connecter à une base de données, il faut tout d'abord charger le pilote. • la documentation du driver fournit le nom de la classe à utiliser.  Par exemple, si le nom de la classe est jdbc.DriverXXX, le chargement du driver se fera avec le code suivant : • Class.forName("jdbc.DriverXXX");  Exemple : Chargement du pilote pour un base Oracle • Class.forName("oracle.jdbc.driver.OracleDriver");
  6. 6. L'établissement de la connexion 6  Pour se connecter à une base de données, il faut instancier un objet de la classe Connection en lui précisant sous forme d'URL la base à accéder. • La syntaxe URL peut varier d'un type de base de données à l'autre.  Exemple : String url = "jdbc:oracle:thin:@sdev01.bkam.ma:1521:BAMDEV"; Connection con = DriverManager.getConnection(url);  Création d'une connexion avec un user et un mot de passe : String url = " jdbc:oracle:thin:@sdev01.bkam.ma:1521:BAMDEV "; Connection con = DriverManager.getConnection(url, "toto", "passwd");
  7. 7. 7 L'exécution de requêtes SQL  Une fois la connexion établie, il est possible d'exécuter des ordres SQL  Les classes qui peuvent être utilisées pour obtenir des informations sur la base de données sont : • DatabaseMetaData : informations à propos de la base de données : nom des tables, index, version ... • ResultSet : résultat d'une requête. L'accès se fait enregistrement par enregistrement. • ResultSetMetaData : informations sur les colonnes (nom et type) d'un ResultSet
  8. 8. L'exécution des requêtes SQL  Les requêtes d'interrogation SQL sont exécutées avec les méthodes d'un objet de la classe Statement que l'on obtient à partir d'un objet de la classe Connection.  L’objet de la classe Statement permet d'envoyer des requêtes SQL à 8 la base.  Le résultat d'une requête d'interrogation est renvoyé dans un objet de la classe ResultSet par la méthode executeQuery(). Exemple : ResultSet résultats = null; String requete = "SELECT * FROM client"; try { Statement stmt = con.createStatement(); résultats = stmt.executeQuery(requete); } catch (SQLException e) { //traitement de l'exception }
  9. 9. L'exécution des requêtes SQL  Pour une requête de type interrogation (SELECT), la méthode à utiliser de la classe 9 Statement est executeQuery().  Pour des traitements de mise à jour, il faut utiliser la méthode executeUpdate(). Elle retourne le nombre d’enregistrement mis à jour.  la méthode executeUpdate() est utilisée également pour exécuter un traitement de type DDL ( Data Definition Langage : définition de données ) comme la création d'un table, elle retourne 0. • Si la méthode retourne 0, cela peut signifier deux choses : le traitement de mise à jour n'a affecté aucun enregistrement ou le traitement concernait un traitement de type DDL.  Exemple : requete = "INSERT INTO client VALUES (3,'client 3','prenom 3')"; try { Statement stmt = con.createStatement(); int nbMaj = stmt.executeUpdate(requete); affiche("nb mise a jour = "+nbMaj); } catch (SQLException e) { e.printStackTrace(); }
  10. 10. 10 Traitement des résultats  La classe ResultSet : C'est une classe qui représente une abstraction d'une table qui se compose de plusieurs enregistrements constitués de colonnes qui contiennent les données.  Les principales méthodes pour obtenir des données sont  • next() : se déplace sur le prochain enregistrement : retourne false si la fin est atteinte • getMetaData() : retourne un objet ResultSetMetaData associé au ResultSet. • getString(int) : retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme d'entier. • getString(String) : retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme d'entier. • Close() : ferme le ResultSet.
  11. 11. 11 Traitement des résultats  La méthode getMetaData() retourne un objet de la classe ResultSetMetaData qui permet d'obtenir des informations sur le résultat de la requête. • Le nombre de colonne peut être obtenu grâce à la méthode getColumnCount() de cet objet.  La méthode next() déplace le curseur sur le prochain enregistrement. • Le curseur pointe initialement juste avant le premier enregistrement. • Donc il est nécessaire de faire un premier appel à la méthode next() pour se placer sur le premier enregistrement. • Des appels successifs à next permettent de parcourir l'ensemble des enregistrements. • Elle retourne false lorsqu'il n'y a plus d'enregistrement
  12. 12. 12 Traitement des résultats  Exemple :  //parcours des données retournées  try { ResultSetMetaData rsmd = résultats.getMetaData(); int nbCols = rsmd.getColumnCount(); boolean encore = résultats.next(); while (encore) { for (int i = 1; i <= nbCols; i++) System.out.print(résultats.getString(i) + " "); System.out.println(); encore = résultats.next(); } résultats.close(); } catch (SQLException e) { //traitement de l'exception }
  13. 13. 13 Traitement des résultats  Les méthodes getXXX() permettent d'extraire les données selon leur type spécifiée par XXX tel que getString(), getDouble(), getInteger(), etc ... .  Il existe deux formes de ces méthodes : • indiquer le numéro de la colonne en paramètre (en commençant par 1) • Ou indiquer le nom de la colonne en paramètre.  La première méthode est plus efficace mais peut générer plus d'erreurs à l'exécution notamment si la structure de la table évolue.
  14. 14. 14 L'utilisation des transactions  Définition : Une transaction permet de ne valider un ensemble de traitements sur la base de données que s'ils se sont tous effectués correctement. • Une transaction est un mécanisme qui permet donc de s'assurer que toutes les opérations qui la compose seront réellement effectuées.  Une transaction est gérée à partir de l'objet Connection. • Par défaut, une connexion est en mode auto-commit • Dans ce mode, chaque opération est validée unitairement pour former la transaction.  Pour pouvoir rassembler plusieurs traitements dans une transaction : • il faut désactiver le mode auto-commit (classe Connection possède la méthode setAutoCommit() qui attend un booléen qui précise le mode de fonctionnement ). • Exemple : • connection.setAutoCommit(false);
  15. 15. 15 L'utilisation des transactions  Une fois le mode auto-commit désactivé, appel à la méthode commit() de la classe Connection permet de valider la transaction courante.  L'appel à cette méthode valide la transaction courante et crée implicitement une nouvelle transaction.  Si une anomalie intervient durant la transaction, il est possible de faire un retour en arrière pour revenir à la situation de la base de données au début de la transaction en appelant la méthode rollback() de la classe Connection
  16. 16. 16 Hibernate : chapitres 1. Présentation framework Hibernate 2. Éléments de base • Beans • Fichier de mapping (fichier XML, annotation) • Fichier de configuration 3. Persistance des objets (lecture, création, modification, suppression) 4. Gestion des transactions 5. Gestion du cache Hibernate 6. Langage de requête (HQL)  requête simple 7. Gestion des relations: • relation de type 1 - 1 (one-to-one) • relation de type 1 - n (one-to-many) • relation de type n - 1 (many-to-one) • relation de type n - n (many-to-many) 8. Héritage : implémentation de deux stratégies 9. Hibernate et Polymorphisme
  17. 17. 17 Hibernate: chapitres 10. Langage de requête (HQL)  requête complexe 11. Fonctions avancées (pagination, itération,..) 12. Utilisation de l’API Criteria  (requête objet avec des critères dynamiques) 13. Externalisation des requêtes 1. Fichiers Texte 2. Fichiers XML 14. API JPA (java persistant API)  Implémentation Hibernate
  18. 18. 18 Présentation Hibernate  Hibernate a besoin de plusieurs éléments pour fonctionner : • une classe de type javabean qui encapsule les données d'une occurrence d'une table • un fichier de correspondance (mapping) qui configure la correspondance entre la classe et la table • des propriétés de configuration notamment des informations concernant la connexion à la base de données  Une fois ces éléments correctement définis, il est possible d'utiliser Hibernate dans le code des traitements à réaliser.  L'architecture d'Hibernate est donc la suivante :
  19. 19. 19 Présentation Hibernate  Hibernate a besoin de plusieurs éléments pour fonctionner : • une classe de type javabean qui encapsule les données d'une occurrence d'une table • un fichier de correspondance (mapping) qui configure la correspondance entre la classe et la table • des propriétés de configuration notamment des informations concernant la connexion à la base de données  Une fois ces éléments correctement définis, il est possible d'utiliser Hibernate dans le code des traitements à réaliser.  L'architecture d'Hibernate est donc la suivante :
  20. 20. 20 Présentation Hibernate Application Classes encapsulant les données Hibernate Base de données Fichier de mapping Propriétés de configuration
  21. 21. 21 Création du Bean  Cette classe doit respecter le standard des javabeans notamment encapsuler les propriétés dans des champs private avec des getters et setters et avoir un constructeur par défaut.  Les types utilisables pour les propriétés sont : les types primitifs, les classes String et Dates, et n'importe quelle classe qui encapsule une autre table ou une partie de la table.
  22. 22. 22 Création du Bean public class Personne { private long identifiant; private String nom; private String prenom; public Personne( String nom, String prenom) { this.nom = nom; this.prenom = prenom; } public Personne() { } public void setIdentifiant(long identifiant) { this.identifiant = identifiant; } public long getIdentifiant() { return identifiant; } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } public String getPrenom() { return prenom; } public void setPrenom(String prenom){ this.prenom = prenom; }
  23. 23. Création du fichier de mapping  Pour assurer le mapping, Hibernate a besoin d'un fichier de correspondance (mapping file) au format XML qui va contenir des informations sur la correspondance entre la classe définie et la table de la base de données.  Différents éléments sont précisés dans ce document XML 23 • la classe qui va encapsuler les données • l'identifiant dans la base de données et son mode de génération • le mapping entre les propriétés de classe et les champs de la base de données • les relations • ...
  24. 24. Création du fichier de mapping 24 (suite)  Le fichier débute par un prologue et une définition de la DTD utilisée par le fichier XML.  Exemple : <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping -2.0.dtd">  Le tag racine du document XML est le tag <hibernate-mapping>. Ce tag peut contenir un ou plusieurs tag <class>.
  25. 25. Création du fichier de mapping 25 (suite) Exemple : <hibernate-mapping> <class name="modele.Commande" table="COMMANDE" > <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="code" type="string" column="code"/> <property name="libelle" type="string" column="libelle" /> <property name="montant" type="string" column="montant" /> </class> </hibernate-mapping>
  26. 26. Création du fichier de mapping 26 (suite)  Le tag <class> permet de préciser des informations sur la classe qui va encapsuler les données.  Ce tag possède plusieurs attributs dont les principaux sont: • name (*) : nom pleinement qualifié de la classe • table (*) : nom de la table dans la base de données • dynamic-update : booléen qui indique de ne mettre à jour que les champs dont la valeur a été modifiée (false par défaut) • dynamic-insert : booléen qui indique de générer un ordre insert que pour les champs dont la valeur est non nulle (false par défaut)
  27. 27. Création d'un fichier de mapping 27 (suite)  Le tag enfant <id> du tag <class> permet de fournir des informations sur l'identifiant d'une occurrence dans la table.  Ce tag possède plusieurs attributs : • name : nom de la propriété dans la classe. • type : le type Hibernate • column : le nom du champ dans la base de données (par défaut le nom de la propriété)  Le tag <generator>, fils obligatoire du tag <id>, permet de préciser quel est le mode de génération d'un nouvel identifiant.  Ce tag possède un attribut : • class (*) : précise la classe qui va assurer la génération de la valeur d'un nouvel identifiant.
  28. 28. Création du fichier de mapping 28 (suite)  Exemple de types de génération fournies en standard par Hibernate (possèdent chacun un nom) : • increment : incrémentation d'une valeur dans la JVM. • sequence : utilisation d'une séquence pour les bases de données qui le supportent (Oracle, DB2, PostgreSQL, ...) <generator class="sequence"> <param name="sequence">SEQ_VARIABLE</param> </generator> • assigned : la valeur est fournie par l'application. • hilo : utilisation d'un algorithme qui utilise une valeur réservée pour une table d'une base de données (par exemple une table qui stocke la valeur du prochain identifiant pour chaque table).
  29. 29. Création du fichier de mapping 29 (suite)  Le tag <property>, fils du tag <class>, permet de fournir des informations sur une propriété et sa correspondance avec un champ dans la base de données.  Ce tag possède plusieurs attributs dont les principaux sont : • name(*) : précise le nom de la propriété. • type : précise le type. Le type doit être soit un type Hibernate (integer, string, date, ...), soit les types primitifs java et certaines classes de base (int, java.lang.String, float, java.util.Date, ...). • column : précise le nom du champ dans la base de données (par défaut le nom de la propriété) • update : précise si le champ est mis à jour lors d'une opération SQL de type update (par défaut true) • insert : précise si le champ est mis à jour lors d'une opération SQL de type insert (par défaut true).
  30. 30. 30 Fichier de configuration  Pour exécuter Hibernate, il faut lui fournir un certain nombre de propriétés concernant sa configuration pour qu'il puisse se connecter à la base de données.  Ces propriétés peuvent être fournies sous plusieurs formes : • un fichier de configuration nommé hibernate.properties et stocké dans un répertoire inclus dans le classpath. • un fichier de configuration au format XML nommé hibernate.cfg.xml • utiliser la méthode setProperties() de la classe Configuration.
  31. 31. Fichier de configuration (suite) 31  Les principales propriétés pour configurer la connexion JDBC sont : • hibernate.connection.driver_class : nom pleinement qualifié de classe du pilote JDBC. • hibernate.connection.url : URL JDBC désignant la base de données • hibernate.connection.username : nom de l'utilisateur pour la connexion • hibernate.connection.password : mot de passe de l'utilisateur. • hibernate.connection.pool_size : nombre maximum de connexions dans le pool.  Les principales autres propriétés sont : • hibernate.show_sql : booléen qui précise si les requêtes SQL générées par Hibernate sont affichées dans la console (particulièrement utile lors du débogage). • hibernate.dialect : nom de la classe pleinement qualifiée qui assure le dialogue avec la base de données
  32. 32. Fichier de configuration (suite) 32 Exemple : <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@sdev01.bkam.ma:1521:BAMDEV</prop erty> <property name="dialect">org.hibernate.dialect.OracleDialect</property> <property name="hibernate.connection.username">username</property> <property name="hibernate.connection.password">password</property> <property name="show_sql">true</property> <!-- Mapping files --> <mapping resource="auth.mapping.xml" /> </session-factory> </hibernate-configuration>
  33. 33. 33 Structure de notre application Hibernate
  34. 34. 34 Utilisation d'Hibernate  Pour utiliser Hibernate dans le code, il est nécessaire de réaliser plusieurs opérations : • création d'une instance de la classe Configuration • création d'une instance de la classe SessionFactory • création d'une instance de la classe Session qui va permettre d'utiliser les services d'Hibernate  Une instance de la classe Session est obtenue à partir d'une fabrique de type SessionFactory.  Cet objet est obtenu à partir de l'instance du type Configuration en utilisant la méthode buildSessionFactory().  La méthode openSession() de la classe SessionFactory permet d'obtenir une instance de la classe Session.
  35. 35. 35 Utilisation d'Hibernate  Par défaut, la méthode openSession() qui va ouvrir une connexion vers la base de données en utilisant les informations fournies par les propriétés de configuration.  Exemple : Configuration config = new Configuration(); config = config.configure("persistence.cfg.xml"); SessionFactory sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession();
  36. 36. 36 Persistance d'une nouvelle instance  Pour créer une nouvelle occurrence dans la source de données, il suffit de créer une nouvelle instance de classe encapsulant les données, de valoriser ces propriétés et d'appeler la méthode save() de la session en lui passant en paramètre l'objet encapsulant les données.  La méthode save() n'a aucune action directe sur la base de données.  Pour enregistrer les données dans la base, il faut réaliser un commit sur transaction ou faire appel à la méthode flush() de la classe Session.
  37. 37. 37 Persistance d'une nouvelle instance public static void main(String args[]) throws Exception { Configuration config = new Configuration(); config = config.configure("persistence.cfg.xml"); SessionFactory sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Commande commande = new Commande(4, "code1", "libelle1", "montant1"); session.save(commande); tx.commit(); session.close(); } catch (Exception e) { if (tx != null) { tx.rollback(); } throw e; } sessionFactory.close(); }
  38. 38. Obtenir une instance à partir de 38 son identifiant  La méthode load() de la classe Session permet d'obtenir une instance de la classe des données encapsulant les données de l'occurrence de la base dont l'identifiant est fourni en paramètre.  Il existe deux surcharges de la méthode : • la première attend en premier paramètre le type de la classe des données et renvoie une nouvelle instance de cette classe • la seconde attend en paramètre une instance de la classe des données et la met à jour avec les données retrouvées
  39. 39. Obtenir une instance à partir de 39 son identifiant (suite) public static void main(String args[]) throws Exception { Configuration config = new Configuration(); config = config.configure("persistence.cfg.xml"); SessionFactory sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession(); try { Commande commande = (Commande) session.load(Commande.class, new Long(3)); System.out.println("nom = " + commande.getLibelle()); } finally { session.close(); } sessionFactory.close(); }
  40. 40. 40 Modifier une instance  Pour mettre à jour une occurrence dans la source de données, il suffit d'appeler la méthode update() de la session en lui passant en paramètre l'objet encapsulant les données.  Le mode de fonctionnement de cette méthode est similaire à celui de la méthode save().  La méthode saveOrUpdate() laisse Hibernate choisir entre l'utilisation de la méthode save() ou update() en fonction de la valeur de l'identifiant dans la classe encapsulant les données.
  41. 41. 41 Modifier une instance (suite) Transaction tx = null; try { tx = session.beginTransaction(); Commande commande = (Commande) session.load(Commande.class, new Long(3)); commande.setLibelle("testlibelle1"); commande.setCode("testcode"); session.update(commande); tx.commit(); session.close(); } catch (Exception e) { if (tx != null) { tx.rollback(); } throw e; } sessionFactory.close(); }
  42. 42. 42 Supprimer une instance Transaction tx = null; try { tx = session.beginTransaction(); Commande commande = (Commande) session.load(Commande.class, new Long(3)); session.delete(commande); tx.commit(); session.close(); } catch (Exception e) { if (tx != null) { tx.rollback(); } throw e; } sessionFactory.close(); }
  43. 43. 43 Le langage de requête HQL  Pour offrir un langage d'interrogation commun à toute les bases de données, Hibernate propose son propre langage nommé HQL (Hibernate Query Language).  Le langage HQL est proche de SQL avec une utilisation sous forme d'objets des noms de certaines entités : il n'y a aucune référence aux tables ou aux champs car ceux ci sont référencés respectivement par leur classe et leurs propriétés.  C'est Hibernate qui se charge de générer la requête SQL à partir de la requête HQL en tenant compte du contexte (type de base de données utilisée, défini dans le fichier de configuration.
  44. 44. 44 Clause from  La requête Hibernate la plus simple est de la forme : • from Commande c where c.code='code1' and c.libelle='libelle2‘ • qui retourne simplement toutes les instances de la classe Commande qui respecte la condition.  Plusieurs classes peuvent apparaître, ce qui conduira à un produit cartésien : • from Commande c, Client cl
  45. 45. 45 Clause from try { Query query = session.createQuery("from Commande where code='code1'"); List commandes = query.list(); for (int i = 0; i < commandes.size(); i++) { Commande personne = (Commande) commandes.get(i); System.out.println("nom = " + personne.getLibelle()); } } finally { session.close(); } sessionFactory.close();
  46. 46. 46 Passage des paramètres  D’autres exemples pour écrire des requêtes HQL : • Query query1 = session.createQuery( "from Commande c where c.code='code1' and c.libelle='libelle2'"); • Query query2 = session.createQuery("from Commande where code=:paramcode"); query2.setString("paramcode", "code1");
  47. 47. 47 Clause « select »  La clause select sélectionne les objets et propriétés qui doivent être retournés dans le résultat de la requête.  Exemple :  Query query = session.createQuery("select c.libelle from Commande c where c.code='code5'");  Query query = session.createQuery("select c.client from Commande c where c.code='code5'");
  48. 48. 48 Fonctions d'agrégation  Les requêtes HQL peuvent aussi retourner le résultat de fonctions d'agrégation sur les propriétés.  Exemple : Pour sélectionner le nombre de client dans la base de données, nous pouvons utiliser la requête suivante : Query query1 = session.createQuery("select count(cl) from Client cl"); List nbrecommandes = query1.list(); for (int i = 0; i < commandes.size(); i++) { Long nbre = (Long) nbrecommandes.get(i); System.out.println("Nobre commandes = " + nbre); }
  49. 49. 49 Clause « order by »  La liste retournée par la requête peut être triée par n'importe quelle propriété de la classe ou du composant retourné.  Exemple Query query = session.createQuery("from Client cl order by cl.nom, cl.prenom"); List commandes = query.list(); for (int i = 0; i < commandes.size(); i++) { Client client= (Client) commandes.get(i); System.out.println("nom = " + client.getNom()); }
  50. 50. 50 Le langage de requête HQL (suite)  Exercice : Utiliser une requête HQL et la méthode delete de la classe Session pour supprimer des enregistrements de la table commande. Utiliser une condition dans la requête de suppression.
  51. 51. 51 Les relations  Un des fondements du modèle de données relationnelles repose sur les relations qui peuvent intervenir entre une table et une ou plusieurs autres tables ou la table elle même.  Hibernate propose de transcrire ces relations du modèle relationnel dans le modèle objet. Il supporte plusieurs types de relations : • relation de type 1 - 1 (one-to-one) • relation de type 1 - n (one-to-many) • relation de type 1 - n (many-to-one) • relation de type n - n (many-to-many)  Dans le fichier de mapping, il est nécessaire de définir les relations entre la table concernée et les tables avec lesquelles elle possède des relations.
  52. 52. Relation de type one-to-many  La relation de type one-to-many est définie quand une classe contient une liste ou une collection d’une autre classe.  Exemple : un client à plusieurs commandes, reflète une relation 1-n. la classe client contient une collection des commandes.  Les deux tables (CLIENT, COMMANDE) sont liées par un le champs identifiant de la table CLIENT. 52
  53. 53. Relation de type one-to-many  Pour mapper une relation one-to-many on doit suivre les 53 opérations suivantes : 1. Créer dans la classe client une collection des commande. 2. Ajouter une colonne dans la table COMMANDE pour faire la relation avec la table client via le champs IDENTIFIANT de cette dernière. 3. Modifier le fichier de mapping en ajoutant la balise suivante dans le mapping de la classe Client. <bag name="commandes" > <key column="CLIENT" /> <one-to-many class="modele.Commande" /> </bag>
  54. 54. Relation de type one-to-many 54 Exemple : <class name="modele.Client" table="CLIENT" > <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <bag name="commandes" > <key column="CLIENT" /> <one-to-many class="modele.Commande" /> </bag> </class>
  55. 55. Relation de type one-to-many  Dans la classe de persistance ajouter les instructions 55 suivantes : 1. Ouvrez une transaction 2. Créer une collection de commandes dans laquelle vous rajoutez une commande. 3. Créer une instance d’un client. 4. Affecter la collection de commandes au client 5. Persister l’objet client en appelant la méthode save de la session hibernate. 6. La même chose pour l objet commande. 7. Commiter la transaction. 8. Fermer la session.
  56. 56. Relation de type one-to-many  Le code qui correspond aux instructions précédentes : tx = session.beginTransaction(); Commande commande = new Commande("code5", 56 "libelle5", "montant5"); Collection commandes = new Vector(); commandes.add(commande); Client client = new Client("issam", "bouzidi"); client.setCommandes(commandes); session.save(client); session.save(commande); tx.commit(); session.close();
  57. 57. Relation de type one-to-many 57  En utilisant le mapping one-to-many la récupération d’un objet père permet la récupération de ses objets fils.  Exemple : la récupération d’un client permet de récupérer aussi ses objets fils : Client client = (Client) session.load(Client.class, new Long(3)); for (Iterator iter = client.getCommandes().iterator(); iter.hasNext();) { Commande commande = (Commande) iter.next(); System.out.println(commande.getLibelle()); }
  58. 58. Relation de type one-to-many 58  Création en cascade : hibernate permet de faire la création dans une relation one-to-many en cascade.  C-a-d que la persistance de l’objet père permet de faire la persistance automatiquement des objets fils. Nous ne sommes pas obliger de faire aussi la persistance des sous objets.  Pour utiliser la persistance en cascade il faut ajouter l’option cascade dans la balise de mapping de la relation one-to-many: <bag name="commandes" cascade="all" > <key column="CLIENT" /> <one-to-many class="modele.Commande" /> </bag>
  59. 59. Relation de type one-to-many  Comme pour la création nous pouvons aussi faire la suppression en cascade. Mais il va falloir être très prudent en utilisant cette option.  La même option utilisée pour la création est 59 utilisée pour la suppression.  Dans le code du service de persistance il suffit de supprimer l’objet client pour que les objets commande qui lui sont liés seront automatiquement supprimés.  Pour supprimer, appeler toujours la méthode delete() de la classe Session.
  60. 60. Relation de type one-to-many 60 Exercice :  Utiliser l’option cascade pour : • Créer et persister automatiquement un client qui possède trois commandes. • Supprimer le client avec tous ses commandes.
  61. 61. Relation de type one-to-many 61 Exemple de suppression en cascade : tx = session.beginTransaction(); Client client = (Client) session.load(Client.class, new Long(1)); tx = session.beginTransaction(); session.delete(client); tx.commit(); session.close();
  62. 62. 62 Tri des collections  Hibernate donne la possibilité de trier une collection récupérée directement à partir d’un objet père :  Exemple dans une relation one to many :  one-to-many: <bag name="commandes" order-by="code asc" > <key column="CLIENT" /> <one-to-many class="modele.Commande" /> </bag>
  63. 63. 63 Initialisation tardive Optimisation du cache  Hibernate donne également la possibilité de ne charger des objets au niveau du cache qu’à la demande par l’application, en utilisant l’option lazy  Exemple <class name="modele.Client" table="CLIENT" lazy="false"> <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <bag name="commandes" cascade="all" order-by="code desc lazy="false"> <key column="CLIENT" /> <one-to-many class="modele.Commande" /> </bag> </class>
  64. 64. 64 Relation de type many-to-one  La relation many-to-one est l’opération inverse de la relation one-many-to.  La relation de type many-to-one est définit quand une classe contient une référence simple vers une classe.  Exemple : plusieurs commandes appartiennent au même client.  Contrainte : l’objet fils ne doit appartenir à deux objet parents.  Exemple : Une commande ne peut pas appartenir à deux client en même temps.
  65. 65. 65 Relation de type many-to-one  Pour mapper une relation many-to-one, par rapport à l’exemple précédent, suivre les étapes suivantes : 1. Ajouter un attribut de type Client dans la classe Commande (bien sur avec les getter et setter) 2. modifier le fichier de mapping en rajoutant la balise suivante dans le mapping de la classe Commande <many-to-one name="client" class="modele.Client" column="CLIENT" />
  66. 66. 66 Relation de type many-to-one  Exemple : <class name="modele.Commande" table="COMMANDE"> <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="code" type="string" column="code" /> <property name="libelle" type="string" column="libelle" /> <property name="montant" type="string" column="montant" /> <many-to-one name="client" class="modele.Client" column="CLIENT" /> </class>
  67. 67. 67 Relation de type many-to-one  Dans la classe de persistance ajouter les instructions suivantes : 1. Ouvrez une transaction 2. Créer une instance de la classe Commande. 3. Récupérer un client de la base de données. 4. Affecter le client à la Commande 5. Persister l’instance de la Commande créée en appelant la méthode save de la session hibernate. 6. Commiter la transaction. 7. Fermer la session.
  68. 68. 68 Relation de type many-to-one  Le code qui correspond aux instructions précédentes : tx = session.beginTransaction(); Commande commande = new Commande("code6", "libelle5", "montant5"); Client client = (Client) session.load(Client.class, new Long(1)); commande.setClient(client); session.save(commande); tx.commit();
  69. 69. 69 Relation de type many-to-one  En utilisant le mapping many-to-one la récupération d’un objet fils permet la récupération de son objet père.  Exemple : la récupération d’une Commande permet de récupérer aussi son propriétaire (c-a-d le client) : Commande commande = (Commande) session.get(Commande.class, new Long(4)); System.out.println(commande.getClient().getNom())
  70. 70. Relation de type many-to-many  Pour mapper une relation many-to-many, en se basant sur un exemple 70 (Client, Fournisseur), il faut suivre les étapes suivantes : 1. Créer une Classe fournisseur et la table correspondante. 2. Ajouter la table de relation entre le client et le fournisseur. Cette table doit contenir une colonne qui correspond à l’identifiant du client et une autre qui correspond à celui du fournisseur. 3. Ajouter un attribut de type Collection de fournisseur dans la classe (bien sur avec les getter et setter) 4. Mapper la nouvelle classe (Fournisseur) 5. modifier le fichier de mapping en rajoutant la balise suivante dans le mapping de la classe Client <bag name="fournisseurs" cascade="all" table="CLIENTFOURNISSEUR"> <key column="CLIENT" /> <many-to-many column="FOURNISSEUR" class="modele.Fournisseur" /> </bag>
  71. 71. Relation de type many-to-many 71  Exemple : <class name="modele.Client" table="CLIENT" > <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <bag name="fournisseurs" cascade="all" table="CLIENTFOURNISSEUR"> <key column="CLIENT" /> <many-to-many column="FOURNISSEUR" class="modele.Fournisseur" /> </bag> </class>
  72. 72. Relation de type many-to-many  Le code qui correspond aux instructions précédentes : Client client = new Client("chafiq", "toto"); Fournisseur fournisseur = new Fournisseur("fourni1"); Collection fournisseurs = new Vector(); fournisseurs.add(fournisseur); client.setFournisseurs(fournisseurs); session.save(client); tx.commit(); 72
  73. 73. Relation de type many-to-many  Si la table de relation contient des champs supplémentaires, nous 73 devons passer par un mapping many-to-one.  Prenant l’exemple précédent. Si la table de relation contient un attribut supplémentaire nous devons suivre les étapes suivantes pour assurer le mapping : 1. Ajouter une nouvelle classe, Affectation par exemple, qui contient l’attribut supplémentaire, et une référence vers l’objet client et lune autre vers l objet fournisseur (il faut pas oublié l’attribut identifiant) 2. Dans la table de relation, ajouter l’attribut supplémentaire. 3. Mapper la classe Affectation en rajoutant deux tags « many-to-one », le premier qui pointe vers la classe fournisseur, et l’autre vers la classe client. • <many-to-one name="client" class="modele.Client" column="CLIENT" /> • <many-to-one name="fournisseur" class="modele.Fournisseur" column="FOURNISSEUR" />
  74. 74. Relation de type many-to-many  Exercice : utilisation d’une table de relation qui contient un attribut supplémentaire. • Affecter un client à un fournisseur dans un local de livraison bien défini. • Récupérer une affectation et afficher le client et le fournisseur qui lui sont associés. 74
  75. 75. Relation de type many-to-many 75  Correction : tx = session.beginTransaction(); Client client = (Client) session.get(Client.class, new Long(1)); Fournisseur fournisseur = (Fournisseur) session.get(Fournisseur.class, new Long(1)); Affectation affectation = new Affectation("local-rabat",client, fournisseur); session.save(affectation); tx.commit();
  76. 76. 76 Relation de type one-to-one  Une association one-to-one vers une autre classe persistante est déclarée en utilisant un élément one-to-one.  Il y a deux types d'association one-to-one: • les associations sur clé primaire • les associations sur clé étrangère unique
  77. 77. 77 Relation de type one-to-one Associations sur clé primaire  Les associations sur clé primaire ne nécessitent pas de colonne supplémentaire dans la table.  Si deux enregistrements sont liés par l'association alors les deux enregistrements partagent la même valeur de clé primaire.  si vous souhaitez que deux objets soient liés par association sur clé primaire, vous devez vous assurer qu'ils aient la même valeur d'identifiant.
  78. 78. 78 Relation de type one-to-one Associations sur clé primaire  Supposons dans cet exemple que nous avons une relation one-to-one entre les deux entités Client et Societe (client ne peut avoir qu’une seule société et qu’une société n’appartient qu’un seul client)  Pour une association par clé primaire, ajoutez les tags suivant dans le mapping des classes Client et Societe, respectivement : • Dans le mapping de la classe Client <one-to-one name= "societe" class="modele.Societe" /> • Dans le mapping de la classe Societe <one-to-one name="client" class="modele.Client"/> constrained : spécifie qu'une contrainte sur la clé primaire de la table mappée fait référence à la table de la classe associée.
  79. 79. 79 Relation de type one-to-one Associations sur clé primaire  Assurez vous que les clés primaires des lignes associées dans les tables CLIENT et SOCIETE sont égales. • Nous utilisons, dans ce cas, une stratégie de génération d'identifiant Hibernate spéciale, appelée foreign: <id name="identifiant" column="IDENTIFIANT"> <generator class="foreign"> <param name="property">client</param> </generator> </id>
  80. 80. 80 Relation de type one-to-one Associations sur clé primaire <class name="modele.Client" table="CLIENT"> <id name="identifiant" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <property name="prenom" type="string" column="PRENOM" /> <one-to-one name= "societe" class="modele.Societe" /> </class>
  81. 81. 81 Relation de type one-to-one Associations sur clé primaire <class name="modele.Societe" table="SOCIETE"> <id name="identifiant" type="long“ column="IDENTIFIANT"> <generator class="foreign"> <param name="property">client</param> </generator> </id> <property name="nom" type="string" column="NOM" /> <property name="adresse" type="string" column="ADRESSE" /> <one-to-one name="client" class="modele.Client" constrained =" true" /> </class>
  82. 82. 82 Relation de type one-to-one Associations sur clé étrangère  Une clé étrangère avec une contrainte d'unicité, de Societe vers Client, peut être déclarée comme : <many-to-one name="client" class="modele.Client" column= "ID_CLIENT" unique="true" />  Et cette association peut être bidirectionnelle en ajoutant ceci dans le mapping de la classe Client : <one-to-one name="societe" class="modele.Societe" />
  83. 83. 83 Relation de type one-to-one Associations sur clé étrangère <class name="modele.Client" table="CLIENT"> <id name="identifiant" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <property name="prenom" type="string" column="PRENOM" /> <one-to-one name="societe" class="modele.Societe" /> </class>
  84. 84. 84 Relation de type one-to-one Associations sur clé étrangère <class name="modele.Societe" table="SOCIETE"> <id name="identifiant" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <property name="adresse" type="string" column="ADRESSE" /> <many-to-one name="client" class="modele.Client" column="IDCLIENT unique="true" /> </class>
  85. 85. 85 Requête HQL (jointure)  Comme nous pouvons faire des requêtes simple avec le langage HQL, nous pouvons également faire des requête complexe en utilisant les jointures.  Exemple : pour sélectionner les commandes dont le code est «05» et le nom utilisateur est «amrani», il faut écrire la requête suivante :  Query query3 = session.createQuery(« select cmd from Commande cmd join cmd.client c where cmd.code='code5' and c.nom=‘amrani'");
  86. 86. 86 Requête HQL (jointure)  La liste résultat de la requête doit retourner une collection de tableau.  Chaque tableau contient un objet commande et un objet client.  Exemple : List commandes = query3.list(); for (int i = 0; i < commandes.size(); i++) { Commande commande = (Commande) commandes.load(i); System.out.println("libelle = " + commande.getLibelle()); System.out.println("prenom = " + commande.getClient().getPrenom()); }
  87. 87. 87 Clause « select »  La clause select sélectionne les objets et propriétés qui doivent être retournés dans le résultat de la requête.  Exemple :  Query query = session.createQuery("select c.client from Commande c where c.code='code5'");
  88. 88. 88 Fonctions d'agrégation  Les requêtes HQL peuvent aussi retourner le résultat de fonctions d'agrégation sur les propriétés.  Exemple : Pour sélectionner le nombre de client dans la base de données, nous pouvons utiliser la requête suivante : Query query1 = session.createQuery("select count(cl) from Client cl"); List nbrecommandes = query1.list(); for (int i = 0; i < commandes.size(); i++) { Long nbre = (Long) nbrecommandes.get(i); System.out.println("Nobre commandes = " + nbre); }
  89. 89. 89 Fonctions d'agrégation  Pour sélectionner la commande qui a le montant le plus élevé, nous pouvons utiliser la requête suivante : Query query1 = session.createQuery("select cmd1 from Commande cmd1 where cmd1.montant = (select max(cmd.montant) from Commande cmd)"); List commandes = query1.list(); for (int i = 0; i < commandes.size(); i++) { Commande commande = (Commande)commandes.get(i); System.out.println("Commande = " + commande.getLibelle()); }
  90. 90. 90 Fonctions d'agrégation  Exercice :  Utiliser le langage HQL pour récupérer, pour chaque client, la somme des montants de ses commandes.  Indication : la fonction qui permet de faire la somme dans le langage HQL est : sum  Affichage : • Nom client = ‘toto’ Somme des montants =150 • Nom client = ‘tata’ Somme des montants =120
  91. 91. 91 Fonctions d'agrégation  Correction : Query query7 = session.createQuery("select sum(cmd.montant), cl.nom from Commande cmd join cmd.client cl group by cl.nom"); List commandes = query7.list(); for (int i = 0; i < commandes.size(); i++) { Object[] objects =(Object[]) commandes.get(i); String nbre = (String) objects[0]; String client = (String) objects[1]; System.out.println("prenom = " + client); System.out.println("Nobre commandes = " + nbre); }
  92. 92. 92 Clause « order by »  La liste retournée par la requête peut être triée par n'importe quelle propriété de la classe ou du composant retourné.  Exemple Query query = session.createQuery("from Client cl order by cl.nom, cl.prenom"); List commandes = query.list(); for (int i = 0; i < commandes.size(); i++) { Client client= (Client) commandes.get(i); System.out.println("nom = " + client.getNom()); }
  93. 93. 93 Héritage  Hibernate permet de faire aussi le mapping de l’héritage.  Hibernate supporte trois stratégie d’héritage : • une table par hiérarchie de classe. • une table par classe fille. • une table par classe concrète.  Nous allons implémenter la première stratégie de l’héritage dans l’exemple suivant.
  94. 94. 94 Héritage  Pour implémenter le mapping de l’héritage il faut suivre les étapes suivantes : 1. Ajouter une hiérarchie de classe (classe mère et des classes filles) 2. Ajouter une table qui contient les attributs de toutes les classes. 3. Dans la table, créée, ajouter un champ qui désigne le type de la classe. 4. Mapper la classe mère et les classes fille en respectant la syntaxe suivante :
  95. 95. 95 Héritage <class name="modele.Personne" table="PERSONNE"> <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <discriminator column="TYPE" type="string" /> <property name="nom" type="string" column="NOM" /> <property name="prenom" type="string" column="PRENOM" /> <subclass name="modele.Etudiant« discriminator-value="ETUDIANT"> <property name="adresse" type="string" column="ADRESSE" /> </subclass> <subclass name="modele.Employe« discriminator-value="EMPLOYE"> <property name="matricule" type="string" column="MATRICULE" /> </subclass> </class>
  96. 96. 96 Héritage  Exercice :  Créer et mapper les classe suivantes : • Personne • Employe • Etudiant  Les classes Employe et Etudiant doivent hériter de la classe Personne.
  97. 97. 97 Héritage  Correction tx = session.beginTransaction(); Etudiant etudiant= new Etudiant("chafiq", "bouzidi","adresse"); Employe employe=new Employe(« amine","amrani","56480"); session.save(employe); session.save(etudiant); tx.commit();
  98. 98. 98 Héritage  Implémentation de l’héritage : une table par classe fille. Pour implémenter le mapping de l’héritage il faut suivre les étapes suivantes : 1. Ajouter une hiérarchie de classe (classe mère et des classes filles) 2. Ajouter une table qui contient les attributs de la classe mère (n’oublier pas l’identifiant). 3. Ajouter une table qui contient les attributs de la classe fille (n’oublier pas l’identifiant). 4. Mapper la classe mère et les classes fille en respectant la syntaxe suivante :
  99. 99. 99 Héritage <class name="modele.Personne" table="PERSONNE"> <id name="identifiant" type="long" column="IDENTIFIANT"> <generator class="increment" /> </id> <property name="nom" type="string" column="NOM" /> <property name="prenom" type="string" column="PRENOM" /> <joined-subclass name="modele.Professeur" table="PROFESSEUR"> <key column="IDPERSONNE" /> <property name="matiere" type="string" column="MATIERE" /> </joined-subclass> </class>
  100. 100. 100 Externaliser des requêtes nommées  Vous pouvez aussi définir des requêtes nommées dans le document de mapping.  Souvenez-vous d'utiliser une section CDATA si votre requête contient des caractères qui pourraient être interprétés comme des éléments XML.
  101. 101. 101 Externaliser des requêtes nommées <query name="PersonneByNomEtPrenom"> <![CDATA[from Personne where nom like ? and prenom=?]]> </query> Query query = session.getNamedQuery("PersonneByNomEtPrenom"); query.setString(0, "chafiq1"); query.setString(1, "issam");
  102. 102. 102 Pagination  Si vous avez besoin de spécifier des liens sur votre ensemble de résultats (le nombre maximum de lignes et/ou la première ligne que vous voulez récupérer) vous pouvez utiliser des méthodes de Query : Query query = session.createQuery("from Personne "); query.setFirstResult(20); query.setMaxResults(10);  Hibernate sait comment traduire cette requête de limite en SQL natif pour votre SGBD.
  103. 103. 103 Itération "scrollable"  Si votre connecteur JDBC supporte les ResultSet s "scrollables", l'interface Query peut être utilisée pour obtenir un objet ScrollableResults, qui permettra une navigation flexible dans les résultats de la requête
  104. 104. 104 Itération "scrollable" Query query = session.createQuery("select prenom, nom from Personne order by prenom"); ScrollableResults persScrol = query.scroll(); persScrol.first(); do { Personne presonne = (Personne) persScrol.get(0); System.out.println(presonne.getNom());} while (persScrol.scroll(5));
  105. 105. 105 Requêtes en SQL native  Vous pouvez construire votre requête en SQL, en utilisant createSQLQuery().  Il est nécessaire de placer vos alias SQL entre accolades Query query = session.createSQLQuery("select nom, prenom from Personne order by identifiant"). addScalar("nom",Hibernate.STRING). addScalar("prenom",Hibernate.STRING); for (int i = 0; i < resultat.size(); i++) { Object[] o= (Object[]) personnes.get(i); System.out.print("Nom = " + o[0] + " : "); System.out.println("Prenom = " + o[1]); }
  106. 106. 106 Requêtes en SQL native : requête d’entités  Les requêtes précédentes ne retournaient que des valeurs scalaires, en ne retournant que les valeurs brutes de l'ensemble de résultats. Ce qui suit montre comment récupérer des entités depuis une requête native SQL, grâce à addEntity(). Query query = session.createSQLQuery("select nom, prenom from Personne order by identifiant").addEntity(Personne.class); for (int i = 0; i < personnes.size(); i++) { Personne personne = (Personne) personnes.get(i); System.out.print("Nom = " + personne.getNom() + " : "); System.out.println("Prenom = " + personne.getPrenom()); }
  107. 107. 107 Requêtes par critères  HQL est extrêmement puissant, mais certains développeurs préfèrent construire des requêtes dynamiquement, en utilisant l'API orientée objet, plutôt que de construire des chaînes de requêtes.  Hibernate fournit une API intuitive de requête Criteria pour ces cas :
  108. 108. 108 Requêtes par critères (Restriction du résultat) Criteria criteria =session.createCriteria(Personne.class). add(Restrictions.eq("prenom", "issam")). add(Restrictions.like("nom", "cha%")); criteria.setFirstResult(5); criteria.setMaxResults(10); List personnes =criteria.list(); for (int i = 0; i < personnes.size(); i++) { Personne personne = (Personne) personnes.get(i); System.out.print("Nom = " + personne.getNom()+ " : "); System.out.println("Prenom = " + personne.getPrenom()); }
  109. 109. 109 Requêtes par critères (Trier les résultats)  Vous pouvez trier les résultats en utilisant org.hibernate.criterion.Order; Criteria criteria =session.createCriteria(Personne.class); criteria.add(Restrictions.like("prenom", "%must%")); criteria.add(Restrictions.like("nom", "%bennoun%")); criteria.addOrder(Order.asc("nom")); criteria.setFirstResult(5); criteria.setMaxResults(10); List personnes =criteria.list();
  110. 110. 110 Requêtes par critères (Association)  Vous pouvez facilement spécifier des contraintes sur des entités liées, par des associations en utilisant createCriteria() : Criteria criteria = session.createCriteria(Client.class); criteria.add(Restrictions.like("prenom", "%must%")); criteria.add(Restrictions.like("nom", "%bennoun%")); criteria.add(Restrictions.between("age", 30, 50)); criteria.addOrder(Order.asc("nom")); criteria.createCriteria("commandes").add(Restrictions.like("code", "001"));
  111. 111. Synchronisation du cache avec 111 la base : méthode flush  Les instances transactionnelles persistantes (objets chargés, sauvegardés, créés ou résultats d'une recherche par la Session) peuvent être manipulées par l'application.  Toute modification sur un état persistant sera sauvegardée (persistée) quand la Session sera flushée.  Le moyen le plus simple de modifier l'état d'un objet est donc de le charger (load()), et de le manipuler pendant que laSession est ouverte :
  112. 112. Synchronisation du cache avec 112 la base : méthode flush Exemple : try { Session session = sessionFactory.openSession(); Client client1 = (Client) session1.load(Client.class, new Long(9)); client1.setNom(« amrani"); session.flush(); session.connection().commit(); } catch (Exception e) { e.printStackTrace(); session2.connection().rollback(); throw e; }

×