Présentation :

Lien vers le powerpoint de notre présentation

Dans les langages objet, les données étant le plus souvent stockées dans des bases de données relationnelles ainsi l’utilisation d’un framework de mapping Objet/Relationnel est recommandé pour assurer la rapidité, l’évolutivité et la maintenabilité des développements. Hibernate, issu de la communauté Open Source, répond à ce besoin et connaît depuis quelques années un vif succès. Ce succès s'explique notamment par son architecture parfaitement adaptable à tout type de développements et le support de la majorité des bases de données du marché.

Pour démarrer :

Hibernate est une surcouche de JDBC qui lui ajoute une dimension objet. Le terme mapping objet/relationnel (ORM) décrit la technique consistant à faire le lien entre la représentation objet des données et sa représentation relationnelle, basée sur un schéma SQL.

Architecture

Concrètement, Hibernate permet de lier/mapper un objet défini en Java avec une table dans une base de données, via un fichier déclaratif de mapping. Le système peut s’occuper de la création des tables en fonction des fichiers de configuration et mettre aussi à jour les tables si nécessaire lors d’un changement dans l’un des fichiers de configuration.

Hibernate possède plusieurs moyens pour effectuer des requêtes. Il est possible d’exprimer des requêtes en SQL, ou en HQL (Hibernate Query Language : language propre à Hibernate) ou encore en critères orientés objet. On notera que pour les utilisateurs d'Eclipse, il existe un plugin : Hibernate Synchroniser, qui permet de faciliter l'utilisation d'Hibernate.

Quelques comparaisons :

Il existe d'autres outils d'ORM permettant d'assurer la persistance de données, comme JDO et TopLink. Pour l'outil d'ORM JDO, on note quelques problèmes de compatibilité avec les EJB V3 (Entreprise Java Bean version 3).

Une application web en Spring developpée avec SpringJDBC avec du traitement automatisé et répétitif semblerait être plus performante à une autre développée avec une couche de persistance O/R telle que Hibernate.

Rétrospection :

Suite à notre expérience de développement du projet de gestion de contacts, nous reviendrons sur les points suivants :

  • L'installation du framework
  • - Son déploiement
  • - Sa configuration
  • - Le mapping (HBM) des objets
  • - La génération des objets métiers
  • Un approfondissement sur des aspects particulier du développement
  • - Des exemples de requêtage
  • - Le mapping many-to-many
  • - Le lazy loading et les JSP
  • - L'encodage en UTF-8

L'installation du framework

Son déploiement

Pour déployer le framework, vous devez ajouter toutes les librairies nécessaires en plus d'hibernate3.jar.
Il ne surtout pas en oublier sinon il apparait des erreurs assez incompréhensibles qui sont des erreurs de chargement de classes par mécanisme d'introspection Java.
Voici la liste de toutes celles que nous avons utilisé pour le projet :

  • antlr-2.7.6.jar
  • dom4j-1.6.1.jar
  • jta-1.1.jar
  • slf4j-jdk14-1.5.2.jar
  • slf4j-log4j12-1.5.2.jar
  • commons-collections-3.1.jar
  • javassist-3.4.GA.jar

Sa configuration

Pour le configurer, vous devez créer ou modifier le fichier hibernate.cfg.xml dans lequel on spécifie les informations de la base de données (adresse, login, mot de passe...) ainsi que le nom de la classe qui créé la premiere instance de la connexion à la base de données et des différents objets sur lesquels on travaille. Celui-ci se trouve à la racine de vos classes Java.
Exemple d'un fichier hibernate.cfg.xml :

Le mapping (HBM) des objets

Vient ensuite la création des objets avec l'extension .hbm dans lesquels on spécifie le nom des attributs de l'objet ainsi que le nom de la colonne à laquelle il se réfère dans la base de données. Plus simplement, il s'agit d'une description de la classe de vos objets, qu'il s'agisse de leurs membres ou leurs relations.
Exemple de fichier User.hbm :

La génération des objets métiers

A l'aide du plug-in d'eclipse Hibernate Synchroniser les classes définissants les objets ainsi que les getteurs, setteurs vont être automatiquement générés.
De base, 3 types de fichiers sont générés : des fichiers "normaux" qui contiennent uniquement les attributs de l'objet, des fichiers "Base" qui contiennent l'ensemble des methodes (getteurs, setteurs) ainsi que des fichiers "DOA" qui ne nous sont pas utiles. Pour desactiver la génération des fichiers DOA il faut faire un clic droit sur le projet puis properties. Il faut ensuite selectionner Hibernate Synchronizer à gauche puis dans l'onglet General, choisir le 2ème onglet "Data Access Object" et décocher "i would like to have DOA created for me".
Toutes les méthodes métier doivent être définies dans le fichier dit "normal" car ce dernier ne sera pas modifié si vous éditez votre mapping et que vous regénérez les classes.

Un approfondissement sur des aspects particuliers du développement

Des exemples de requêtage

La dernière étape consiste à créer les requêtes dans la base de données. Attention le langage utilisé est le HQL et non le SQL. Il faut utiliser le nom de la classe des objets et non le nom de la colonne dans la base de données.
Exemple 1 : récupérer une liste d'utilisateur

Un deuxième exemple : ajout en base de données

Le mapping many-to-many

Dans le cas d'une relation n-->n ou 1-->n dans un MCD, il existe une option à spécifier dans Hibernate pour générer automatiquement les liaisons entre les objets : many-to-many pour n-->n et one-to-many pour 1-->n. Cette option est à rajouter dans le fichier de mapping définissant l'objet entre les balises <class>.
Exemple pour un Utilisateur qui connait d'autres utilisateurs (on dit que la table de transition s'appelle contacts) :

On peut observer l'utilisation d'un noeud "set" qui se traduira par une collection Java du type Set. Mais il existe d'autres types disponibles, telles les Map par exemple.

Le lazy loading et les JSP

Un problème que vous pouvez rencontrer concerne le lazy-loading. Avant tout, un petit rappel sur ce qu'est le lazy-loading : Hibernate essaie d'optimiser l'accès à la base de données. Prenons le cas d'une composition. Si vous chargez le composé, les composant ne seront peut-être pas tous, et entièrement chargés en mémoire. Seule une référence vers ses objets, ou quelques membres déjà lus sont en mémoire. Imaginez maintenant qu'une fois le traitement fait dans votre servlet, vous décidiez d'afficher des informations d'un objet précédemment chargé. Si la partie que vous avez récupérée n'a pas été entièrement chargée et que vous tentez de l'afficher dans la JSP, vous obtiendrez une exception vous précisant que la session Hibernate a été fermée.

Que faire alors ? Simplement demander le chargement complet des objets. Autrement dit : le full-loading. Pour se faire, il vous faudra modifier l'attribut lazy à false d'un des noeuds du fichier de mapping de votre objet. Pour savoir quel noed modifier, reportez-vous à la document et la XSD des fichiers HBM.

L'encodage en UTF-8

Un point intéressant qui mérite d'être soulevé est l'encodage en UTF-8. Celui-ci se configure dans le fichier de configuration hibernate.cfg.xml. Pour cela, il suffit de rajouter :

Il se peut aussi que l'on puisse préciser le charset dans les paramètres de l'URI de connexion à la base de données. De plus, n'oubliez pas de préciser le bon interclassement dans votre SGBD.

Cas d'étude

Lien vers le .war de notre projet

Bibliographie :