Développons en Java 2.30 | |
Copyright (C) 1999-2022 Jean-Michel DOUDOUX | (date de publication : 15/06/2022) |
|
Niveau : | Supérieur |
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.
Les principaux buts de JDO sont :
Le développement avec JDO se déroule en plusieurs étapes :
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.
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 |
|
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 :
Pour des raisons de facilité, le répertoire courant "." est ajouté dans le CLASSPATH. Le pilote JDBC pour MySQL est aussi ajouté à cette variable.
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; }
} |
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();
}
} |
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.
... |
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> |
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)
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) |
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) |
L'API de JDO se compose de deux packages :
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.
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.
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.
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 :
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.
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.
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 :
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.
La classe JDOHelper permet de faciliter l'utilisation de JDO grâce à plusieurs méthodes statiques pouvant être regroupées dans plusieurs catégories :
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) |
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) |
La mise en oeuvre de JDO requiert plusieurs étapes :
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.
Cette classe va réaliser des traitements en utilisant JDO pour accéder et/ou mettre à jour des données.
|
La suite de cette section sera développée dans une version future de ce document
|
Toutes les classes écrites doivent être compilées normalement comme toutes classes Java.
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.
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.
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 |
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 |
|
La suite de ce chapitre sera développée dans une version future de ce document
|
|