J. D. O. (2002)

Home

Le logo de JDOJava Data Objects : objets de données Java.

Besoin

Gérer la persistance d'objets Java de manière :

Analyse

JDO vise à ajouter à des POJO une capacité de persistance de manière "orthogonale", c'est-à-dire sans contraintes pour ces objets (suivant en cela l'approche AOP, en ajoutant un aspect "persistance" aux objets).

En particulier il vise à garantir une indépendance :

JDO accède au support de stockage (datastore) via le moyen de son choix. Il peut s'agir de pilotes JDBC ou de connecteurs JCA dans le cas d'applications J2EE.

Cas d'utilisation

On peut distinguer 3 types de classes dans une application utilisant JDO :

Persistence capable

Un objet JDO persistence-capable est un objet Java capable d'être :

Cette capacité lui est donnée après modification de son code (généralement son code compilé, ou bytecode) par outil. Cette instrumentation du code après compilation est appelée enhancement (enrichissement de code). Cet enhancement se base sur un descriptif des classes à rendre persistence-capable (définissant les classes et champs à rendre persistants, les champs caractérisant l'identité d'un objet, etc.), nommé métadonnées (metadata).

L'ensemble des états décrits ci-dessus (transactionnel-persistant, transactionnel-transitoire) est généralement qualifié d'ensembles des états "gérés" (managed), puisque c'est dans ces cas que la gestion JDO apporte une valeur ajoutée. Ceci dit un objet enhancé peut également passer en état transitoire-non transactionnel, c'est à dire ayant un comportement identique à des objets Java classiques ou JDO ne s'interpose plus.

Outre sa classe et les champs qui composent son état, un objet Persistence Capable est caractérisé par son identité qui peut être :

Persistence aware

Les classes manipulant les objets persistence capable effectuent des :

Conception

Persistence capable

Pour être géré (managed) par JDO, un objet doit implémenter un contrat de Persistence Capable via une instrumentation (enhancement) du bytecode de sa classe. Cette post-compilation ajoute au code des méthodes et champs additionnels, et du code statique permettant d'interragir avec l'infrastructure JDO (de tel ou tel fournisseur, l'enhancement étant standard et n'imposant donc pas de modification des classes métier si l'on change de fournisseur JDO).

Comme il s'agit de l'implémentation d'une interface, il est également possible - mais jamais fait en pratique - d'utiliser d'autres techniques que l'enhancement, telle que :

La correspondance (mapping) entre l'état mémoire de l'objet et son état persistant est rédigé dans un descripteur standard, externe au code (fichier XML), pouvant comporter des extensions propriétaires.

L'accès aux données peut être :

Implémentation

Etats JDO
  Transactionnel Non transactionnel
Persistant   Lectures
Transitoire   Comportement identique à celui d'un objet non JDO
Optimisations Ecriture dans le cache NonTransactionalWrite=true  
Lecture non synchronisée NonTransactionalRead=true  
Recherche dans le cache ignoreCache=false  

 

  Type Description
Optimisations Conservation du cache après transaction retainValues=true
Non-restauration après annulation restoreValue=false
  Ecriture dans le cache NonTransactionalWrite=true
Lecture non synchronisée NonTransactionalRead=true
Recherche dans le cache ignoreCache=false
Transactions JDO

Egalement le JDO Query Language (JDOQL) permet d'obtenir des instances ou collections d'instances JDO d'un type donné, éventuellement filtrées par divers critères exprimés dans une syntaxe proche de celle du langage Java.

Filtres JDOQL
    Forme Commentaire
Egalité Avec contante champ == valeur, champ != valeur, champ == null, champ != null  
Entre champs champ1 == champ2  
Comparaison Caractères chaîne > valeur
chaîne < valeur
chaîne1 < chaîne2
chaîne1 > chaîne2
Pour les types non numérique, l'interprétation est dépendante de l'implémentation / du support de persistance
chaîne.startsWith (valeur), chaîne.endsWith (valeur)  
Expression expression1 && expression2
expression1 || expression2
 
Collections Existence d'un élément caractérisé collection.contains (var) && expression (var)  
Vide collection.isEmpty()  

Des contraintes peuvent également être imposées sur les ensembles résultats retournés, qui peuvent être :

API

L'API de JDO est définie dans le package javax.jdo.

On peut distinguer trois types de classes dans une application JDO :

Une implémentation JDO doit au moins supporter une des identités SGBD.

SPI

En dehors de l'API visible par les développeurs utilisant JDO, comment cela fonctionne-t-il "à l'intérieur" ?

A l'exécution, toute instance JDO "enhancée" référence un gestionnaire de son état (StateManager) qui communique avec le PersistenceManager pour gérer la persistance.

Le StateManager, chargé de gérer le cycle de vie d'une (ou plusieurs) instances, considère plusieurs états possibles dans la vie du d'un PersistenceCapable :

FAQ

FUD

Notes

Exemples

Un exemple de classe persistante est n'importe quelle classe POJO.

Un exemple de code JDO est :

import javax.jdo.*;

// Code code suppose que pm réference un PersistenceManager et qu'il y a un contexte transactionnel en cours

Employee jerome = new Employee ("Jérôme", "Beau");
Address jeromeAddress = new Address("71 rue Desnouettes", "75015", "Paris");
jerome.setAddress (jeromeAddress);

Transaction tx = pm.currentTransaction();
tx.begin();
{
   ProjectId lidoProjectId = new ProjectId ("LiDO", 3.1);         // Identifiant métier du projet
   Project lidoProject = pm.getObjectById (lidoProjectId, true);  // Récupère le projet en base

   jerome.getProjects().add (lidoProject);
   lidoProject.getWorkers().add (jerome);
   pm.makePersistent (jerome);   // Rend aussi jeromeAddress persistant, de proche en proche (clôture transitive)
}
tx.commit();   // Ecrit les jerome et jeromeAddress en base

tx.begin();
{
   // Récupère les projets dont le nom commence par "L", dont les collaborateurs et travaillent à Paris ou qui contiennent le collaborateur jerome
   Query query = pm.newQuery (Projet.class, "workers.contains(aPeople) && aPeople.address.city == someCity && name.startsWith(\"L\"") || aPeople == somePeople");
   myQuery.declareVariables  ("Employee aPeople");
   myQuery.declareParameters ("String someCity, Employee somePeople");
   myQuery.setOrdering ("name ascending, manager.name ascending");   // Trie les résultat par nom de projet puis éventuellement par nom du manager du projet
   Collection foundProjects = (Collection) myQuery.execute (jerome, "Paris");  // Exécute la requête avec les arguments suivants
   Iterator foundProjectsIterator = foundProjects.iterator();
   while (iter.hasNext()) {
      Project aFoundProject = (Project) foundProjectsIterator.next();

      // Utilise projet
   }
   myQuery.close (result);
}
tx.commit();

pm.close();

Un exemple de descripteur JDO standard est :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "jdo.dtd">
<jdo>
  <package name=”net.javarome.jdo.samples”>

    <class name=”Person” identity-type=”application” objectidclass=”PersonKey”>
      <field name=”nom” primary-key=”true”/>
    </class>

    <class name=”Employe” identity-type=”application” persistence-capable-superclass="Person">
      <field name=”salaire” default-fetch-group=”true”/>
      <field name=”dept”/>
      <field name=”chef”/>
    </class>

    <class name=”Project” identity-type=”application”>
      <field name=”nom” primary-key=”true”/>
      <field name=”workers”>
        <collection element-type=”Employe”/>
      </field>
    </class>

  </package>

</jdo>

Implémentations JDO
  Fournisseur Exadel Object Frontier OSS Object Industries Versant Solarmetric Xcalia (LIBeLIS) ObjectDB Software (Apache) Jakarta SignSoft (Apache)
Produit Exadel JDO Frontier Suite for JDO JPOX JRelay JDO Genie

Judo / enJin

Fast Objects Kodo JDO LiDO ObjectDB OJB intelliBO TJDO
Version   3 1   2   j2 2 3     3 2
Domaine Technologie Release   0 1   0     5 1       0
Standard JDO Version 1.0 1.0 2.0--           2.0--        
Cache Partagé / niveau 2 Entre PM     Oui   Oui   Active Java Cache Oui lido.cache.mode=shared     CacheConfiguration. setUseNTXCache (true)  
Entre PMF               JMS ou TCP

lido.cache.mode=shared
lido.cache.group= myMultiplePmfGroup

(si même JVM)

       
Agrafage d'objets               DataCache.pin(objectId) pin(object) ou lido.cache.classStrategy (myClassName)= pinned    
 
Par classe         Extension cache-strategy=yes|all d'une classe     Extension can-cache =true d'une classe (défaut) Oui     CacheConfiguration. setUseNTXCache (false)  
Distribué   Version entreprise Oui   JMS Via cache listeners plugins, JDOGenie Servers   Non kodo.DataCache via DataRepository API     JMS, TCP  
JCache     Non         Oui via DataRepository API        
Pluggable     Oui           Oui        
Tangosol     Oui         kodo.DataCache: tangosol(TangosolCacheName=kodo, TangosolCacheType=distributed) via DataRepository API        
Exclusif                 lido.cache.exclusive=true        
Evénements               kodo.event.RemoteCommitProvider: jms ou tcp lido.cache.CommitListeners= com.acme.MyCommitListener        
Requêtes JDO QL Extensions String         toLowerCase()     stringContains() caseInsStarts() caseInsEnds() caseInsContains() toLowerCase() toUpperCase()     Non charAt() length() startsWith(substr,pos) substring(begin,end) toLowerCase() toUpperCase()
Map         containsKey(key) contains(value) isEmpty()     containsKey(key) containsValue(value) containsKey(key) containsValue(value)     Non  
Curseurs Mono-transaction         randomAccess= true     com.solarmetric.kodo. ResultListProperties cursor= basic        
Cross-transactions                 cursor= cross-pm        
Taille paramétrable                 fetch-size=n LIDOHINT        
Cache des résultat               kodo.QueryCache: CacheSize=n Oui        
Chargement Grappe         fetch-group=fields     Eager Fetching
Personnalisable Fetch groups
load= dfg| true     JDOQLQuery. addFetchGroupAttribute ("myAttribute");  
SQL Libre     Oui   Oui Non   sqlEmbed

query = pm.newQuery ("sql")
query.setFilter ("where ...")
query.setFilter ("select ...")

Non   SQLQuery query = QueryFactory. newSQLQuery() Oui
Procédures stockées                 query.setFilter ("call ...")        
Transactions Distribuées (XA)   Oui     Oui   Non Oui Oui     Oui  
Optimistes Versionnage Oui Oui Oui Oui N° version, Ttimestamp Non Non Extension jdbc-version-ind" value="version-number" champ JDO sélectionné (lido.optimistic.class.MyClass =selected sur champ int ou Date) Oui   Extension optimistic-lock (timestamp ou version)  
Champs modifiés Oui Tous, champs modifiés, champ / classe Non
Ecriture non transactionnelle   Non Non Oui   Non Non Oui Oui Oui      
Lecture non transactionnelle   Oui Oui Oui   Non Non Oui Oui Oui      
Environnement Intégration serveurs applicatifs   Weblogic, WebSphere, JBoss, Orbix E2A, Oracle 9i, HP AS, Orion, JRun   JCA

Via MBeans (WLS 7.0, JBoss 2.4, 3.0, WAS 5.0)

  Non DataSource (Jboss, WebLogic, WenSphere, SunOne, JRun, Borland)
JCA     JCA  
Attacher/détacher (JDO 2.0)               Oui Oui        
Stockage SGBDR CloudScape Non Oui   Non Non Non Non 4.0.6 Oui Non   Non 4.0.6, 5.0.9
DB2 7.1 Oui   07.02.0000 Oui Non Oui 7.2 Oui Non   Oui 7.2.3
FireBird Non Non   Non 1.0.2 Non Non Non Oui Non   Non 1.0.0.796
HSQL DB Non Non   Non Non Non Non 1.6 Oui Non   Non Non
Ingres Non Non   Non Non Non Non Non Oui Non Non Non Non
Informix Non Oui   Non 9 Non Non Oui Oui Non   7.31 Non
InstantDB Non Non   Non Non Non Non 3.26 Oui Non   3.14 Non
Interbase Non Non   Non 6 Non Non Non Oui Non   Non Oui
JDataStore Non Non   Non       Oui          
MS Access Non Oui   Non Non Non Non Oui Oui Non   Non Non
MS FoxPro Non Non           Oui          
MS SQL Server 8.0 Oui   7.0 7.0 Non Oui 8.0 Oui Non   Oui 7.0 SP4, 2000 SP2
McKoi Non Non   Non Non Non Non Non Oui Non   Non Non
MySQL Non Oui   Non 3.23.49, 4.0.12 Non Non 3.23 Oui Non   Oui 3.23.55-max
Oracle 8.1, 9.2 Oui   8.1.7 8.1.7 Non Oui 8.1-9.1 Oui Non   8.1.7 8.1.7.4.0
Pervasive SQL Non Non   Non Non Non Non Non   Non Non Oui Non
PointBase Non Oui   Non 4.5 Non Non 4.2 Oui Non   Non Non
PostgreSQL Non Non   7.1.3 7.3.1 Non Non 7.2.1 Oui Non   Oui 7.2.1, 7.3.1, 7.3.2-1
Progress Non Non   Non Non Non Non Non   Non Non Oui Non
SAP DB Non Non   Non 7.3 Non Non Non   Non   Oui 7.4.3 Build 010-120-035-462
Sybase Non Oui   Non 11.9.2, 12.5 Non Non 12.5 Oui Non   Oui Non
Unisys Non Non   Non Non Non Non Non Oui Non Non Non Non
SGBDO Versant Non Non Non Non Non Oui Non Oui Oui Non Non Oui Non
Autre Propriétaire Non     Non     Non Non FDB ObjectDB      
Autre               Via dictionnaire fourni Non        
XML Non   Non Non     Non Non Oui Non   Oui  
Instance Identité Durable Datastore   Oui Oui Oui   Oui Oui Oui Oui Oui      
Applicative   Oui Oui Oui Génération automatique de classe Non Non Oui Génération automatique de classe et de valeurs Non      
Personnalisé     Oui           OidProvider        
SGBD                 Champs identité, séquences, tables        
Non durable   Oui Non Non   Non Non Oui Non        
Changement   Non Non Non   Non Non Oui Non        
Transactionnelles Transitoire       Oui       Oui Oui Oui      
Persistante       Oui       Oui Oui Oui      
Non transactionnelles Transitoire       Oui       Oui Oui        
Persistante     Oui Oui       Oui Oui        
Détachement/attachement                 Oui        
Collections Nulles   Oui Oui Non   Non Oui Oui Non Oui      
Tableaux Array[]   Non Oui Oui Oui Oui Oui Oui Oui Oui     Non
int[][], byte[][]                 Oui        
int[][][], byte[][][]                 Oui        
Dictionnaires Map   Non Non Oui Oui Oui Oui Oui Oui Oui     Oui
HashSet   Oui Oui Oui Oui Oui Oui Oui Oui Non     Non
HashMap   Non Oui Oui Oui Non Oui Oui Oui Oui     Non
TreeMap   Non Oui Oui Non Non Non Oui Oui Oui     Non
Hashtable   Non Oui Oui Oui Oui Non Oui Oui Oui     Non
Listes List   Oui Oui Oui Oui Oui Oui Oui Oui Oui     Non
ArrayList   Oui Oui Oui Oui Oui Oui Oui Oui Oui     Non
LinkedList   Oui Oui Oui Oui Oui Oui Oui Oui Oui     Non
Vector   Oui Oui Oui Oui Oui Non Oui Oui Oui     Non
Ensembles Set   Oui Oui Oui Oui Oui Non Oui Oui Oui     Oui
TreeSet   Oui Oui Oui Non Oui Non Oui Non Oui     Non
Développement Outils Mapping graphique Oui             Non LiDO Studio JDO Explorer      
Navigateur de modèle               Non Navilis      
Génération de schéma Oui   Oui         Oui DefineSchema, LPM   schemagen  
Retro- ingénierie de schéma               Oui Pour XML   ClassGenerator  
Evolution de schéma               Oui DefineSchema      
Intégration IDE JBuilder Non   Non       6 Oui Non     Oui  
TCC Non   Non       Non Non Lido 1.4     Oui  
Sun ONE Studio Non           Oui Oui Non     Non  
Eclipse / WSAD Non   Oui       Non Oui 2.x (LiDO Studio)     Non  
API Métadonnées               Oui          
Javadoc               XDocLet JDODocLet        
Taglib Non               Oui        
    Suppressions en cascade Non       Extension dependent du champ collection     Extensions dependent, value-dependent, key-dependent et element-dependent Automatique pour collections en reverse , sinon en partie via l'extension sql-delete-behavior (sinon InstanceCallback)     Extension cascade-delete du champ  
Mapping Classe Plusieurs tables Non Oui           Extension table du champ collection. Clés primaires différentes supportées Oui        
Héritage Vertical Oui       Non     Oui <inheritance-strategy type="per-class">     Extension inheritance d'une classe  
Horizontal Non       Non     Oui <inheritance-strategy type="per-concrete-class"> (défaut)     Non  
Autre               Possible          
Plat / Filtré Non     Oui Oui     Oui <inheritance-strategy type="per-hierarchy">     Oui  
Relations 1-1       Oui           Oui        
Inversée                 Oui        
1-n Table de liaison Oui   Oui   Oui     Oui Oui (défaut)        
Inversée (non ordonnée)         Extension inverse du champ collection     Extension inverse du champ collection <associate field="f" to-column="c">        
n-m Table de liaison Oui   Oui   Oui     Oui Oui        
Inversée (non ordonnée)       Oui Extension inverse du champ collection     Oui Non        
Champs Convertisseurs Oui       JdbcConverter     custom-mapping=ClassMapping, extension column-length CustomMapper, CustomizableMapper        
DataStore Multiples Non       Extension datastore d'une classe     Non Non        

Limitations

Références

Home