Hibernate 3.0 ajoute la persistance des documents XML

03/05/2005

La nouvelle version d’Hibernate, passé sous le giron de JBoss, permet de prendre en compte, grâce à DOM4j, le traitement et la transformation des documents XML pour rendre leurs données facilement persistantes.

Hibernate est un framework Java de persistance qui permet de faire correspondre des tables de base de données relationnelle avec des objets java simples (POJO ou «Plain Old Java Object»). Une fois la correspondance entre les deux mondes définie, le programme Java peut manipuler toutes les données en utilisant que des JavaBean, masquant alors totalement la base de données sous-jacente et ses spécificités. Le framework assure le remplissage de ces objets et la mise à jour de la base en se basant sur leur contenu. Avant la sortie de la version 3 de ce framework, XML constituait déjà le format de description de la correspondance entre les tables relationnelles et les classes Java.

Hibernate 3 franchit un pas supplémentaire. De la même façon que les POJO permettent de manipuler des objets dont les données sont stockées dans une base de données, cette nouvelle fonctionnalité permet de s’affranchir des solutions XML propriétaires. En effet, chaque fournisseur, se devant de se préoccuper de l’importation/exportation des données XML, fournit une solution qui lui est propre à défaut de se baser sur un standard.

Le framework Hibernate permet d’obtenir une représentation XML du résultat d’une requête. Il permet aussi de rendre persistant, c’est-à-dire d’insérer ou de mettre à jour des données dans la base de données depuis des fragments de document XML de façon très simple et similaire à la manipulation de POJO.

Pour illustrer ces ajouts, prenons l’exemple (extrêmement simple) d’une table contenant une liste de tâches à faire, les fameux TODO. Voici une définition SQL possible de la table TODO_TASK:

CREATE TABLE TODO_TASK (
  TODOID INTEGER NOT NULL PRIMARY KEY,
  SUMMARY VARCHAR(45) NOT NULL ,
  DESCRIPTION VARCHAR(45),
  PRIORITY INTEGER,
  DONE TIMESTAMP);

Hibernate permet non seulement de définir une correspondance entre cette table et un bean Java, mais également entre la table et un document XML. Dans cet exemple, le structure des données XML sera la suivante :

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
  <class name="TodoTask"
         table="todo_task" node="todo">
    <id name="todoid" node="@id"/>
    <property name="summary" not-null="true" node="sum"/>
    <property name="description" node="descr"/>    <property name="priority" node="@priority"/>
<property name="doneDate" column="done"/>
  </class>
</hibernate-mapping>

Ainsi, Hibernate fera une correspondance automatique entre, par exemple, le contenu du noeud sum, fils du noeud todo et la colonne summary. Par ailleurs, la colonne done sera disponible dans les beans Java (via la propriété doneDate), mais ne le sera pas dans les fragments XML.

La gestion du XML est assurée par DOM4j. Cette librairie très complète offre le support de DOM, SAX et JAXP mais également des requêtes XPath et de XSLT. Ainsi un document provenant au programme sous une forme SOAP par exemple, peut être transformé dans le format XML pivot par le biais d’une transformation XSLT avant d’être pris en compte par Hibernate. Il peut alors être délivré sous une autre forme, comme un format de sortie SVG, par une autre transformation XSLT. L’association DOM4j/Hibernate permet donc de définir le format XML qui sera utilisé par le métier et délivre un environnement complet de transformation et de traitement de l’information.

Le bout de code Java suivant montre comment, à partir d’un fichier XML, contenant une liste de tâches, hibernate met à jour la base de données relationnelle :

SAXReader sr=new SAXReader(false);
Document doc=null;

try {
  doc = sr.read(ClassLoader.getSystemClassLoader().
                getResourceAsStream("todo-ex.xml"));
} catch (DocumentException e} { ...} 

List todo=doc.selectNodes("//todo");

Session session = sessionFactory.openSession();

Session xmlSession = session.getSession(EntityMode.DOM4J);
Transaction tx=session.beginTransaction();

for (Iterator it=todo.iterator(); it.hasNext(); ) {
xmlSession.saveOrUpdate(”bean.TodoTask”,it.next());
}

tx.commit();

session.close();

Le document est lu grâce à un analyseur syntaxique SAX. La requète XPath permet d’obtenir une liste de tâches Todo. Puis, une session est ouverte. Elle est de type «EntityMode.DOM4J», ce qui indique au framework qu’il doit utiliser la librairie XML et que les données se trouvent dans des fragments XML et non dans des POJO. La boucle les parcourt et les fournit à la session XML qui se charge de mettre la base de données à jour. Le fait de spécifier bean.TodoTask lors de l’action sur la base, permet au framework de connaître à quelle correspondance les noeuds «todo» font référence.

De façon similaire, la consultation de la base peut se faire ainsi :

Element root=docFactory.createElement("todolist");
Document doc=docFactory.createDocument(root) ; Session session = sessionFactory.openSession();

Session xmlSession = session.getSession(EntityMode.DOM4J);
List res=(List) xmlSession.createQuery("from TodoTask").list();

for (int i=0; i<res.size(); i++){
  Element elt = (Element) res.get(i);
  root.add(elt);
}

session.close();

Un document hôte est créé de façon classique. La racine accueillera les différents éléments issus du résultat de la requête. Pour afficher le document XML, DOM4j fournit une classe XMLWriter :

XMLWriter xw;

try {
  xw = new XMLWriter(System.out, new OutputFormat("  ",true));
  xw.write(doc);
} catch (Exception e) {...}

Avec cette nouvelle version, Hibernate facilite non seulement la persistance en offrant une couche d’abstraction par rapport à la base de données, mais il permet désormais d’intégrer des données provenant de documents XML, de messages SOAP, de messages JMS, etc… Même si Hibernate n’a pas vocation à devenir un framework spécialiste du XML, cette extension au monde XML renforce les possibilités offertes par le framework pour assurer un découplage des objets métier avec les détails de mise en oeuvre du stockage en base de données relationnelle.

voir aussi :