IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

 

Développons en Java   2.30  
Copyright (C) 1999-2022 Jean-Michel DOUDOUX    (date de publication : 15/06/2022)

[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ]      [Accueil ]

 

60. JDO (Java Data Object)

 

chapitre    6 0

 

Niveau : niveau 4 Supérieur 

niveau 3 Technologie legacy
Ce chapitre est conservé pour des raisons historiques

 

JDO (Java Data Object) est la spécification du JCP numéro 12 qui propose une technologie pour assurer la persistance d'objets Java dans un système de gestion de données. La spécification regroupe un ensemble d'interfaces et de règles qui doivent être implémentées par un fournisseur tiers.

La version 1.0 de cette spécification a été validée au premier trimestre 2002. Elle permet de réaliser le mapping entre des données stockées dans un format particulier (bases de données ...) et un objet, ce qui a toujours été difficile. JDO propose de faciliter cette tâche en fournissant un standard.

Ce chapitre contient plusieurs sections :

Remarque : face à l'insuccès de JDO, il est dorénavant préférable d'utiliser JPA.

 

60.1. La présentation de JDO

Les principaux buts de JDO sont :

  • la facilité d'utilisation (gestion automatique du mapping des données)
  • la persistance universelle : persistance vers tout type de système de gestion de ressources (bases de données relationnelles, fichiers, ...)
  • la transparence vis à vis du système de gestion de ressources utilisé : ce n'est plus le développeur mais JDO qui dialogue avec le système de gestion de ressources
  • la standardisation des accès aux données
  • la prise en compte des transactions

Le développement avec JDO se déroule en plusieurs étapes :

  1. écriture des objets contenant les données (des beans qui encapsulent les données) : un tel objet est nommé instance JDO
  2. écriture des objets qui utilisent les objets métiers pour répondre aux besoins fonctionnels. Ces objets utilisent l'API JDO.
  3. écriture du fichier metadata qui précise le mapping entre les objets et le système de gestion des ressources. Cette partie est très dépendante du système de gestion de ressources utilisé
  4. enrichissement des objets métiers
  5. configuration du système de gestion des ressources

JDBC et JDO ont les différences suivantes :

JDBC
JDO
orienté SQL orienté objets
le code doit être ajouté explicitement code est ajouté automatiquement
  gestion d'un cache
  mapping réalisé automatiquement ou à l'aide d'un fichier de configuration au format XML
utilisation avec un SGBD uniquement utilisation de tout type de format de stockage

JDO est une spécification qui définit un standard : pour pouvoir l'utiliser il faut utiliser une implémentation fournie par un fournisseur. Plusieurs implémentations existent et le choix de l'une d'elle doit tenir compte des performances, du prix, du support des cibles de stockage des données, etc ... L'intérêt des spécifications est qu'il est possible d'utiliser le même code avec des implémentations différentes tant que l'on utilise uniquement les fonctionnalités précisées dans les spécifications.

Chaque implémentation est capable d'utiliser un ou plusieurs systèmes de stockage de données particulier (base de données relationnel, base de données objets, fichiers, ...).

Attention : tous les objets ne peuvent pas être rendus persistants avec JDO.

 

60.2. Un exemple avec Lido

Les exemples de cette section ont été réalisés avec Lido Community Edition version 1.4.5. de la société Libelis.

Remarque : la société Libelis, renommée en Xcalia n'existe malheureusement plus. Le contenu de ce chapitre est conservé à titre indicatif.

Pour lancer l'installation, il suffit de double cliquer sur le fichier LiDO_Community_1[1].4.5.jar ou de saisir la commande :

Installation de Lido community edition de Libelis
 
java -jar LiDO_Community_1[1].4.5.jar

L'installation s'opère simplement en suivant les différentes étapes de l'assistant.

Le premier exemple permet simplement de rendre persistant un objet instancié dans une base de données MySQL.

Pour faciliter la mise en oeuvre des différentes étapes, un script batch pour Windows sera écrit tout au long de cette section et exécuté. Ce script débute par une initialisation de certaines variables d'environnement.

Début du script
@echo off
REM - script permettant la compilation, l'enrichissement, la creation du schema de 
REM - base de données et l'execution du code de test de JDO avec Lido 1.4.5.
set LIDO_HOME=C:\java\LiDO
set JAVA_HOME=C:\java\j2sdk1.4.2_02

echo initialisation
echo.
SET OLD_PATH=%PATH%
SET PATH=%LIDO_HOME%\bin;%JAVA_HOME%\bin

SET OLD_CLASSPATH=%CLASSPATH%
SET CLASSPATH=.;.\mm.mysql-2.0.14-bin.jar
SET CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\tools.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-api.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\jdo_1_0_0.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\j2ee.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\bin
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-dev.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-rdb.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-rt.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido.tasks
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido.tld
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\skinlf.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\connector_1_0_0.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\jta_1_0_1.jar

Le début du script initialise 4 variables :

  • LIDO_HOME : cette variable contient le chemin du répertoire dans lequel Lido a été installé
  • JAVA_HOME : cette variable contient le chemin du répertoire dans lequel J2SDK a été installé
  • PATH : cette variable contient les différents répertoires contenant des exécutables
  • CLASSPATH : cette variable contient les différents répertoires et fichiers jar nécessaires pour la compilation et l'exécution

Pour des raisons de facilité, le répertoire courant "." est ajouté dans le CLASSPATH. Le pilote JDBC pour MySQL est aussi ajouté à cette variable.

 

60.2.1. La création de la classe qui va encapsuler les données

Le code de cet objet reste très simple puisque c'est simplement un bean encapsulant une personne contenant des attributs nom, prenom et datenaiss.

Exemple :
package testjdo;

import java.util.*;

public class Personne {
      private String nom ="";
      private String prenom = "";
      private Date datenaiss = null;

      public Personne(String pNom, String pPrenom,Date pDatenaiss) {
            nom=pNom;
            prenom=pPrenom;
            datenaiss=pDatenaiss;   
      }

      public String getNom() { return nom; }

      public String getPrenom() { return prenom;}

      public Date getDatenaisse() { return datenaiss; }

      public void setNom(String pNom) { nom = pNom; }

      public void setPrenom(String pPrenom) { nom = pPrenom; }

      public void setDatenaiss(Date pDatenaiss) { datenaiss = pDatenaiss; }

}

60.2.2. La création de l'objet qui va assurer les actions sur les données

Cet objet va utiliser des objets JDO pour réaliser les actions sur les données. Dans l'exemple ci-dessous, une seule action est codée : l'enregistrement dans la table des données du nouvel objet de type Personne instancié.

Exemple :
package testjdo;

import javax.jdo.*;
import java.util.*;

public class PersonnePersist {

      private PersistenceManagerFactory pmf = null;
      private PersistenceManager        pm = null;
      private Transaction               tx  = null;

      public PersonnePersist() {
            try {
            
            pmf = (PersistenceManagerFactory) (
            Class.forName("com.libelis.lido.PersistenceManagerFactory").newInstance());
            pmf.setConnectionDriverName("org.gjt.mm.mysql.Driver");
            pmf.setConnectionURL("jdbc:mysql://localhost/testjdo");          
      } catch (Exception e ){
            e.printStackTrace();
            }
      }

      public void enregistrer() {
            Personne p = new Personne("mon nom","mon prenom",new Date());
            pm = pmf.getPersistenceManager();
            tx = pm.currentTransaction();
            tx.begin();
            pm.makePersistent(p);
            tx.commit();
            pm.close();
      }

      public static void main(String args[]) {
            PersonnePersist pp = new PersonnePersist();
            pp.enregistrer(); 
      }
}

 

60.2.3. La compilation

Les deux classes définies ci-dessus doivent être compilées normalement en utilisant l'outil javac.

Exemple :
...
echo Compilation en cours
javac -classpath %CLASSPATH% testjdo\*.java
echo Compilation effectuee
echo.
...

 

60.2.4. La définition d'un fichier metadata

Le fichier metadata est un fichier au format XML qui précise le mapping à réaliser.

Exemple : metadata.jdo
<? xml version="1.0" ?>
<!DOCTYPE jdo SYSTEM "jdo.dtd">
<jdo>
  <package name="testjdo">
    <class name="Personne" identity-type="datastore">
      <field name="nom" />
      <field name="prenom" />
      <field name="datenaiss" />
    </class>
  </package>
</jdo>

 

60.2.5. L'enrichissement des classes contenant des données

Pour permettre une bonne exécution, il faut enrichir l'objet Personne compilé avec du code pour assurer la persistance par JDO. Lido fournit un outil pour réaliser cette tâche. Cet outil dépend de l'implémentation qui en est faite par le fournisseur de la solution JDO.

La suite du script : enrichissement
...
echo Enrichissement
java -cp %CLASSPATH% com.libelis.lido.Enhance -metadata metadata.jdo -verbose
echo Enrichissement effectue
echo.
...

Le fichier Personne.class est enrichi (sa taille passe de 867 octets à 9693 octets)

 

60.2.6. La définition du schéma de la base de données

Lido fournit un outil qui permet de générer les tables de la base de données. Ces tables contiennent le mapping de la base de données ainsi que les données techniques nécessaires aux traitements.

Les paramètres nécessaires à l'outil de Libelis pour définir le schéma de la base de données doivent être rassemblés dans un fichier .properties.

propriété pour une base de données de type MySQL
# lido.properties file
# jdo standard properties
javax.jdo.option.connectionURL=jdbc:mysql://localhost/testjdo
javax.jdo.option.ConnectionDriverName=org.gjt.mm.mysql.Driver
javax.jdo.option.connectionUserName=root
javax.jdo.option.connectionPassword=
javax.jdo.option.msWait=5
javax.jdo.option.multithreaded=false
javax.jdo.option.optimistic=false
javax.jdo.option.retainValues=false
javax.jdo.option.restoreValues=true
javax.jdo.option.nontransactionalRead=true
javax.jdo.option.nontransactionalWrite=false
javax.jdo.option.ignoreCache=false


# set to PM, CACHE, or SQL to have some traces
# ex:
#lido.trace=SQL,DUMP,CACHE

#  set the Statement pool size
lido.sql.poolsize=10
lido.cache.entry-type=weak

# set the max batched statement
# 0: no batch
# default is 20

lido.sql.maxbatch=30
lido.objectpool=90

# set for PersistenceManagerFactory pool limits
lido.minPool=1
lido.maxPool=10

jdo.metadata=metadata.jdo

Il suffit alors d'utiliser l'application DefineSchema fournie par Lido en lui passant en paramètre le fichier .properties et le fichier .jdo

La suite du script : création du schéma de la base de données
 ...
echo DefineSchema en cours
java com.libelis.lido.DefineSchema -properties testjdo.properties -metadata metadata.jdo
echo DefineSchema termine
echo.
...

Il est facile de vérifier les traitements effectués par l'outil DefineSchema :

Exemple :
C:\java\testjdo>mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 25 to server version: 4.0.16-nt

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use testjdo
Database changed
mysql> show tables;
+-------------------+
| Tables_in_testjdo |
+-------------------+
| lidoidmax         |
| lidoidtable       |
| t_personne        |
+-------------------+
3 rows in set (0.00 sec)

mysql> describe lidoidmax;
+----------+------------+------+-----+---------+-------+
| Field    | Type       | Null | Key | Default | Extra |
+----------+------------+------+-----+---------+-------+
| LIDOLAST | bigint(20) | YES  |     | NULL    |       |
+----------+------------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> describe lidoidtable;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| LIDOID   | bigint(20)   |      | PRI | 0       |       |
| LIDOTYPE | varchar(255) | YES  | MUL | NULL    |       |
+----------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> describe t_personne;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| LIDOID    | bigint(20)  |      | PRI | 0       |       |
| nom       | varchar(50) | YES  |     | NULL    |       |
| prenom    | varchar(50) | YES  |     | NULL    |       |
| datenaiss | datetime    | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> select * from t_personne;
Empty set (0.39 sec)

 

60.2.7. L'exécution de l'exemple

Exemple :
@echo off
REM - script permettant la compilation, l'enrichissement, la creation du schema de 
REM - base de données et l'execution du code de test de JDO avec Libelis 1.4.5.
set LIDO_HOME=C:\java\LiDO
set JAVA_HOME=C:\java\j2sdk1.4.2_02

echo initialisation
echo.
SET PATH=%LIDO_HOME%\bin;%JAVA_HOME%\bin

SET CLASSPATH=.;.\mm.mysql-2.0.14-bin.jar
SET CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\tools.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-api.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\jdo_1_0_0.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\j2ee.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\bin
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-dev.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-rdb.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido-rt.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido.tasks
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\lido.tld
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\skinlf.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\connector_1_0_0.jar
SET CLASSPATH=%CLASSPATH%;%LIDO_HOME%\lib\jta_1_0_1.jar

echo Compilation en cours
javac -classpath %CLASSPATH% testjdo\*.java
echo Compilation effectuee
echo.

echo Enrichissement
java -cp %CLASSPATH% com.libelis.lido.Enhance -metadata metadata.jdo -verbose
echo Enrichissement effectue
echo.

echo DefineSchema en cours
java com.libelis.lido.DefineSchema -properties testjdo.properties -metadata metadata.jdo
echo DefineSchema termine
echo.

echo Execution du test
java -cp %CLASSPATH% testjdo.PersonnePersist
echo Execution terminee
echo.

A l'issu de l'exécution, un enregistrement est créé dans la table qui mappe l'objet Personne.

Exemple :
 mysql> select * from t_personne;
+--------+---------+------------+---------------------+
| LIDOID | nom     | prenom     | datenaiss           |
+--------+---------+------------+---------------------+
|      1 | mon nom | mon prenom | 2004-01-23 20:06:11 |
+--------+---------+------------+---------------------+
1 row in set (0.00 sec)

 

60.3. L'API JDO

L'API de JDO se compose de deux packages :

  • javax.jdo : ce package est à utiliser par les développeurs pour utiliser JDO
  • javax.jdo.spi : ce package est à utiliser par les tiers pour développer une implémentation de JDO

Le package javax.jdo contient essentiellement des interfaces ainsi que quelques classes notamment la classe JDOHelper et les diverses exceptions utilisées par JDO. Les interfaces définies sont : Extent, PersistenceManager, PersistenceManagerFactory, Query etTransaction.

Les exceptions définies par l'API JDO sont : JDOCanRetryException, JDODataStoreException, JDOException, JDOFatalDataStoreException, JDOFatalException, JDOFatalInternalException, JDOFatalUserException, JDOUnsupportedOptionException et JDOUserException.

 

60.3.1. L'interface PersistenceManager

Cette interface définit les méthodes pour l'objet principal de l'API JDO pour les développeurs.

Certaines méthodes permettent de gérer le cycle de vie d'une instance d'un objet de type PersistenceCapable.

Méthode Rôle
void close() Fermer
Transaction currentTransaction() Renvoyer la transaction courante
void deletePersistent() Permettre de détruire dans la source de données l'instance encapsulée
Extent getExtent(Class, boolean) Renvoyer une collection d'instance encapsulant les données dans la source de données
void makePersistent() Permettre de rendre persistantes les données encapsulées dans l'instance en créant une nouvelle occurrence dans le système de gestion de ressources
void evict() Permettre de préciser que l'instance n'est plus utilisée
Query newQuery() Renvoyer un objet de type Query qui permet d'effectuer des sélections dans la source de données
void refresh() Permettre de redonner à une instance les valeurs contenues dans le système de gestion de ressources

Cette interface propose aussi deux méthodes possédant de nombreuses surcharges de la méthode newQuery() pour obtenir une instance d'un objet de type Query.

 

60.3.2. L'interface PersistenceManagerFactory

Un objet qui implémente cette interface à pour but de fournir une instance d'une classe qui implémente l'interface PersistenceManager. Un tel objet doit être configuré via des propriétés pour instancier un objet de type PersistenceManager. Ces propriétés doivent être fournies à la fabrique avant l'instanciation du premier objet de type PersistenceManager. Il n'est dès lors plus possible de changer la configuration de la fabrique.

Cette interface possède une méthode nommée getPersistenceManager() qui permet d'obtenir une instance de la classe PersistenceManager.

 

60.3.3. L'interface PersistenceCapable

Cette interface doit être implémentée lors de son enrichissement par la classe qui va contenir des données. A l'origine, la classe n'implémente pas cette interface ; pour assurer la persistance des données, l'implémentation de l'interface et la définition des méthodes de l'interface seront réalisées lors de la phase d'enrichissement.

Cet enrichissement peut se faire de deux façons :

  • manuellement : ce qui peut être long et fastidieux
  • automatiquement avec un outil fourni avec l'implémentation de JDO : généralement cet outil utilise un fichier au format XML pour obtenir les informations nécessaires à la génération des méthodes

Les méthodes définies dans cette interface sont à l'usage de JDO : une fois la classe enrichie, il ne faut surtout pas appeler directement ces méthodes : elles sont toutes préfixées par jdo.

Une classe qui implémente l'interface PersistenceCapable est nommée instance JDO.

 

60.3.4. L'interface Query

Cette interface définit des méthodes qui permettent d'obtenir des instances représentant des données issues de la source de données.

L'interface définit plusieurs surcharges de la méthode execute() pour exécuter la requête et renvoyer un ensemble d'instances.

La méthode compile() permet de vérifier la requête et préparer son exécution.

La méthode setFilter() permet de préciser un filtre pour la requête.

Une instance d'un objet implémentant l'interface Query est obtenue en utilisant une des nombreuses surcharges de la méthode newQuery() d'un objet de type PersistenceManager.

 

60.3.5. L'interface Transaction

Cette interface définit les méthodes pour la gestion des transactions avec JDO.

Elle possède trois méthodes principales qui sont classiques dans la gestion des transactions :

  • begin : indique le début d'une transaction
  • commit : valide la transaction
  • roolback : invalide la transaction et annule toutes les opérations qu'elle contient

 

60.3.6. L'interface Extent

Une classe qui implémente cette interface permet d'encapsuler toute une collection contenant tous les objets d'un type PersistenceCapable particulier. La méthode iterator() renvoie un objet de type Iterator qui permet de parcourir l'ensemble des éléments de la collection.

L'interface Extent ne prévoit actuellement aucun moyen de filter les éléments de la collection et il est uniquement possible d'obtenir toutes les occurrences.

La méthode close(Iterator) permet de fermer l'objet de type Iterator passé en paramètre.

 

60.3.7. La classe JDOHelper

La classe JDOHelper permet de faciliter l'utilisation de JDO grâce à plusieurs méthodes statiques pouvant être regroupées dans plusieurs catégories :

  • connaitre l'état d'une instance JDO.

    Nom Rôle
    boolean isDeleted(Object) renvoie un booléen qui précise si l'instance JDO fournie en paramètre vient d'être supprimée dans le système de gestion de ressources
    boolean isDirty(Object) renvoie un booléen qui précise si l'instance JDO a été modifiée dans la transaction courante
    boolean isNew(Object) renvoie un booléen qui précise si l'instance JDO fournie en paramètre vient d'être rendue persistante en créant une nouvelle instance dans le système de gestion de ressources
    boolean isPersistent(Object)  
    boolean isTransactional(Object)  

  • obtenir des objets de l'implémentation JDO

    Nom Rôle
    PersistenceManager getPersistenceManager(Object) renvoie l'objet de type PersistenceManager utilisé pour rendre persistante l'instance JDO fournie en paramètre
    getObjectId(Object)  
    makeDirty(Object, String)  
    PersistenceManagerFactory getPersistenceManagerFactory(Properties)  

 

60.4. La mise en oeuvre

La mise en oeuvre de JDO requiert plusieurs étapes :

  • définition d'une classe qui va encapsuler les données (instance JDO)
  • définition d'une classe qui va utiliser les données
  • compilation des deux classes
  • définition d'un fichier de description
  • enrichissement de la classe qui va contenir les données

 

60.4.1. La définition d'une classe qui va encapsuler les données

Une telle classe se présente sous la forme d'un bean : elle représente une occurrence particulière dans le système de stockage des données.

Cette classe n'a pas besoin ni d'utiliser ni d'importer de classes de l'API JDO.

Pour la classe qui va contenir des données, JDO impose la présence d'un constructeur sans argument. Celui-ci est automatiquement ajouté à la compilation si aucun autre constructeur n'est défini, sinon il faut ajouter un constructeur sans argument manuellement.

 

60.4.2. La définition d'une classe qui va utiliser les données

Cette classe va réaliser des traitements en utilisant JDO pour accéder et/ou mettre à jour des données.

 

en construction
La suite de cette section sera développée dans une version future de ce document

 

60.4.3. La compilation des classes

Toutes les classes écrites doivent être compilées normalement comme toutes classes Java.

 

60.4.4. La définition d'un fichier de description

Pour indiquer à JDO quelles classes doivent être persistantes et préciser des informations concernant ces dernières, il faut utiliser un fichier particulier au format XML. Ce fichier désigné par "Metadata" dans les spécifications doit avoir pour extension .jdo.

Il est possible de définir un fichier de description pour chaque classes persistantes ou un fichier pour un package concernant toutes les classes persistantes du package. Dans le premier cas, le fichier doit se nommer nom_de_la_classe.jdo, dans le second nom_du_package.jdo.

Le fichier commence par un prologue :

<?xml version="1.0" encoding="UTF-8" ?>

Le fichier contient ensuite la DTD utilisée pour valider le fichier : soit une URL pointant sur la DTD du site de Sun soit une DTD sur le système de fichier.

<!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 1.0//EN" "http://java.sun.com/dtd/jdo_1_0.dtd">

Le tag racine du document XML est <jdo>. Ce tag peut contenir un ou plusieurs tags <package> selon les besoins, chaque tag package concernant un seul package.

Chaque tag <package> contient autant de tags <class> que de classes de type instance JDO utilisées. L'attribut "name", obligatoire, permet de préciser le nom de la classe.

 

Les tags <jdo>, <package>, <class> et <field> peuvent aussi avoir un tag <extension> qui va contenir des paramètres particuliers dédiés à l'implémentation de JDO utilisée. Il faut un tag <extension> pour chaque implémentation utilisée.

 

60.4.5. L'enrichissement de la classe qui va contenir les données

Cette phase permet d'ajouter du code à chaque classe encapsulant une instance JDO. Ce code contient les méthodes définies par l'interface PersistenceCapable.

Le ou les outils fournis par le fournisseur sont particuliers pour chaque implémentation utilisée.

 

60.5. Le parcours de toutes les occurrences

Un objet qui implémente l'interface Extent permet d'accéder à toutes les instances d'une classe encapsulant des données.

Un objet de type Extent est obtenu en appelant la méthode getExtent() d'un objet PersistentManager. Cette méthode attend deux paramètres : un objet de type Class qui est la classe encapsulant les données et un booléen qui permet de préciser si les sous-classes doivent être prises en compte.

Un objet de type Extent ne permet qu'une seule opération sur l'ensemble des instances qu'il contient : obtenir un objet de type Iterator qui permet le parcours séquentiel de toutes les occurrences. La méthode iterator() permet de renvoyer cet objet de type Iterator : les méthodes hasNext() et next() assurent le parcours des occurrences.

L'appel de la méthode close() une fois que l'objet de type Iterator fourni en paramètre n'a plus d'utilité est obligatoire pour permettre de libérer les ressources allouées par l'objet pour son fonctionnement. La méthode closeAll() permet de fermer tout les objets de type Iterator instanciés par l'objet de type Extent.

Exemple : Afficher tous les données de la table personne
package testjdo;

import javax.jdo.*;
import java.util.*;

public class PersonneExtent {

  private PersistenceManagerFactory pmf = null;
  private PersistenceManager pm = null;

  public PersonneExtent() {
    try {

      pmf =
        (PersistenceManagerFactory) (Class
          .forName("com.libelis.lido.PersistenceManagerFactory")
          .newInstance());
      pmf.setConnectionDriverName("org.gjt.mm.mysql.Driver");
      pmf.setConnectionURL("jdbc:mysql://localhost/testjdo");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void afficherTous() {
    pm = pmf.getPersistenceManager();

    Extent personneExtent = pm.getExtent(Personne.class, true);

    Iterator iter = personneExtent.iterator();
    while (iter.hasNext()) {
      Personne personne = (Personne) iter.next();
      System.out.println(personne.getNom() + " " + personne.getPrenom());
    }
    personneExtent.close(iter);
  }

  public static void main(String args[]) {
    PersonneExtent pe = new PersonneExtent();
    pe.afficherTous();
  }
}
Exemple : Contenu de la table au moment de l'exécution
C:\mysql\bin>mysql testjdo
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3 to server version: 4.0.16-nt

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql< select * from t_personne;
+--------+---------+------------+---------------------+
| LIDOID | nom     | prenom     | datenaiss           |
+--------+---------+------------+---------------------+
|      1 | mon nom | mon prenom | 2004-01-23 20:06:11 |
|   1025 | Nom1    | Jean       | 2004-02-10 00:20:39 |
|   2049 | Nom4    | Jean       | 2004-02-10 00:25:09 |
|   3073 | Nom3    | Louis      | 2004-02-10 21:36:32 |
+--------+---------+------------+---------------------+
4 rows in set (0.00 sec)

mysql<
Résultat :
Execution du test
mon nom mon prenom
Nom1 Jean
Nom4 Jean
Nom3 Louis
Execution terminee

 

60.6. La mise en oeuvre de requêtes

Avec JDO, les requêtes sont mises en oeuvre grâce à un objet de type Query. Les requêtes appliquent un filtre sur un ensemble d'objets encapsulant des données. Ces données sont encapsulées dans un objet de type Extent ou une collection.

Un filtre est une expression booléenne appliquée à chacune des occurrences : la requête renvoie toutes les occurrences pour lesquelles le résultat de l'évaluation de l'expression est vrai. Les expressions sont exprimées avec un langage particulier nommé JDO Query Langage (JDOQL)

Une instance d'un objet qui implémente l'interface Query est obtenue en utilisant la méthode newQuery() d'un objet de type PersistanceManager.

Exemple : afficher les occurrences dont le prénom est Jean
package testjdo;

import javax.jdo.*;
import java.util.*;

public class PersonneQuery {

  private PersistenceManagerFactory pmf = null;
  private PersistenceManager pm = null;

  public PersonneQuery() {
    try {

      pmf =
        (PersistenceManagerFactory) (Class
          .forName("com.libelis.lido.PersistenceManagerFactory")
          .newInstance());
      pmf.setConnectionDriverName("org.gjt.mm.mysql.Driver");
      pmf.setConnectionURL("jdbc:mysql://localhost/testjdo");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void filtrer() {
    pm = pmf.getPersistenceManager();

    Extent personneExtent = pm.getExtent(Personne.class, true);
    String filtre = "prenom == \"Jean\"";
    
    Query query = pm.newQuery(personneExtent, filtre);
    query.setOrdering("nom ascending, prenom ascending");
    Collection result = (Collection) query.execute();

    Iterator iter = result.iterator();
    while (iter.hasNext()) {
      Personne personne = (Personne) iter.next();
      System.out.println(personne.getNom() + " " + personne.getPrenom());
    }
    query.close(result);
  }

  public static void main(String args[]) {
    PersonneQuery pq = new PersonneQuery();
    pq.filtrer();
  }
}
Résultat :
Execution du test
Nom1 Jean
Nom4 Jean
Execution terminee

 

en construction
La suite de ce chapitre sera développée dans une version future de ce document

 

 


[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ]      [Accueil ]

78 commentaires Donner une note à l´article (5)

 

Copyright (C) 1999-2022 Jean-Michel DOUDOUX. Vous pouvez copier, redistribuer et/ou modifier ce document selon les termes de la Licence de Documentation Libre GNU, Version 1.1 ou toute autre version ultérieure publiée par la Free Software Foundation; les Sections Invariantes étant constitués du chapitre Préambule, aucun Texte de Première de Couverture, et aucun Texte de Quatrième de Couverture. Une copie de la licence est incluse dans la section GNU FreeDocumentation Licence. La version la plus récente de cette licence est disponible à l'adresse : GNU Free Documentation Licence.