P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ "PEOPLE SAY NOTHING IS IMPOSSIBLE, BUT I DO NOTHING EVERY DAY." Articles | Connexion
 
~Les Java Data Objects

Précédent  
  Java  
  Suivant
 Présentation

Les Java Data Objects, ou JDO, désignent une spécification destinée à la persistance des données en Java. Parmi l'ensemble de ses caractéristiques, nous pouvons en isoler certaines, très importantes. En premier lieu, JDO implique une notion de transparence. En dehors de certaines instruction explicites (telle l'appel de méthode makePersitent) ou des début et fin de transaction, la gestion de la persistance des données ne doit pas paraître aux yeux du développeur. Nous pouvons comparer cet acte implicite à la gestion de la mémoire par le ramasse-miettes (GC) de la machine virtuelle. Vient ensuite l'universalité du support. Nous choisirons dynamiquement le type de support utilisé comme support de stockage, que cela soit des bases de données ou des fichiers. En outre, le même objet JDO doit fonctionner de manière similaire dans tout autre environnement Java, sans intervention particulière. Nous pouvons également compter sur l'élimination des syntaxes spécialisées. Ainsi, des requêtes SQL disparaîtront pour laisser place au seul langage Java. L'approche pour le programmeur se révèle donc particulièrement consistante, quelle que soit la source de données sélectionnée. Une syntaxe particulière, le JDO Query Language (ou JDOQL) unifie le langage des requêtes et Java.
 Sommaire


 Mécanismes sous-jacents

Afin de rendre un objet persistant, nous devons le décrire par l'entremise d'une syntaxe XML abstraite. Celle-ci se trouve employée dans un fichier de méta-données qui, dans le monde JDO, s'intitule metadata.jdo. Ce fichier explique précisément de quelle manière comment aura lieu la persistance : quels sont les champs à traiter, détermination des clés, noms des champs, et ainsi de suite.

A l'instar de RMI, l'utilisation de JDO nécessite une opération d'enrichissement (ou enhancement) du bytecode. Toutefois, en lieu et place des "stubs" et "skeletons" nous modifions ici directement le fichier .class de la classe Java dont les objets seront persistants.

Le second mécanisme vital concerne la définition de schéma. Il s'agit ici de rédiger un fichier de propriétés caractérisant le type de support employé pour la gestion de la persistance, le pilote, l'URL de connexion, les informations d'identification, et ainsi de suite. Dans le cas d'un stockage au sein d'une base de données, nous pourrons nous reposer sur une base existante ou en générer une nouvelle à partir du fichier de méta-données.

Cette technologie rentre dans le vaste domaine du mapping d'objets, dont le représentant le plus en vogue est le mapping d'objets relationnel. En d'autres termes, si elle a été conçue pour opérer indépendamment du type de support, les bases de donnes relationnelles représentent le choix le plus courant, pour le moment. L'emploi de JDO prend toute sa valeur dans le cadre de la persistance automatique d'objets. Par exemple, sur un serveur d'application J2EE, les Enterprise Java Beans Container-Managed Persistence (EJB CMP) pourront bénéficier de toute la puissance de cette technologie. La norme J2EE Connector Architecture (JCA) instaure à cet effet une collaboration pour permettre à JDO de se substituer au moteur interne de persistance du serveur.


 Persistons dans nos démarches

Les Java Data Objects sont soumis à une spécification de Sun Microsystems, actuellement en version 1.0.1. Outre l'implémentation de référence, JDO RI du même auteur, nous pouvons en trouver de nombreuses autres. Deux compagnies en particulier proposent leurs outils. Nous avons ainsi LiDO de LIBeLIS, et Kodo JDO de Solarmetrics. La première offre notamment un serveur d'application Java Open Source intitulé Orcas, qui nous permettra de nous essayer facilement à LiDO. Pour rester dans le monde de l'Open Source, sachez que TJDO et OJB offrent des solutions alternatives intéressantes. Bien que parfaitement conformes à la spécification de Sun Microsystems, ces dernières se révèlent malheureusement moins abouties que celles précédemment citées. Dans cet article, nous ferons appel à LiDO en version communauté et au bien connu gestionnaire base de données MySQL.

Nous allons découvrir comment appliquer les traitements JDO adéquats à de simples classes Java prenant la forme de Java Beans, c'est-à-dire offrant une collection d'accesseurs et de mutateurs. Par ailleurs, nous utiliserons le terme générique de source de données et laisserons de côté l'appellation base de données. Bien que nos exemples reposent sur MySQL, nous pourrions envisager des fichiers XML, un système de gestion de base de données orienté objet.

Au commencement, aucun objet du système d'informations ne peut candidater au processus de persistance, même si nous les avons décrit dans le fichier de méta-données. Seul un appel à la méthode makePersistent() activera le système de persistance. Cette invocation peut d'ailleurs se révéler inutile si nous rendons persistant un objet contenant une référence vers un autre, toujours "temporaire". La persistance de ce dernier sera appliquée grâce au phénomène de "persistance par liaison". Enfin, sachez que la spécification JDO prévoir la gestion des transactions. Nous pourrons donc effectuer des opérations de lecteur, d'écriture, et de modification en accès concurrent suivant deux algorithmes, l'un dit optimiste et l'autre dit pessimiste.


 Premier exemple

Avant de nous intéresser aux cas complexes de l'aggrégation, de la composition, de l'héritage et des collections, nous allons apprendre à faire persister une classe simple, nantie de quelques accesseurs et mutateurs. Imaginons que notre système nécessite de conserver des informations sur des personnes, représentées par la classe Person définie dans le listing 1. La première tâche du développeur consiste à décrire les objets persistants dans le fichier metadata.jdo. Les quelques lignes suivantes présentent son contenu dans le cas de notre classe company.Person :

<jdo>
  <package name="company">
    <class name="Person" />
  </package>
</jdo>
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Il s'agit ici d'une description minimal. Dans ce cas précis, JDO considérera la classe comme globalement persistante. Tous ses champs le seront donc. Nous retrouvons ici l'une des caractéristiques évoquées précédemment, la transparence du procédé. Il va de soi que seules les classes désignée dans metadata.jdo pourront bénéficier de cette technologie. Après compilation du code source Java, le programmeur doit procéder à l'étape d'enrichissement. Dans notre cas, nous devrons exécuter la commande suivante dans la console système :

java com.libelis.lido.Enhance -metadata metadata.jdo
       
      
JextCopier dans Jext
Nous adaptons ainsi notre bytecode à l'API JDO. L'étape suivant consiste à définir le schéma d'accès à la source de données. Pour ce faire, une nouvelle commande doit être saisie dans la console système !

java com.libelis.lido.ds.jdbc.DefineSchema -properties lido_mysql.properties -c
       
      
JextCopier dans Jext
Le fichier auquel nous faisons ici appel se trouve sur le CD-Rom accompagnant le magazine et contient toutes les propriétés nécessaires pour désigner la base de données Test du serveur MySQL local comme source de données. Il vous faudra impérativement posséder le driver MySQL pour JDBC.

En modifiant le fichier lido_mysql.properties puis en exécutant de nouveau cette commande, vous changerez rapidement et efficacement le type de source de données. Encore une fois, l'opération se révèle transparente au final pour le développeur. L'option -c utilisée dans notre exemple demande la création des tables dans la base de données. Evidemment, si celles-ci existent déjà, son emploi les détruira. Sachez enfin que malgré l'utilisation d'un fichier de propriétés externe, nous pourrions tout à fait déclarer chacune d'entre elle au cour même de notre programme, dans le code source. Nous perdrions toutefois une certaine souplesse.

Au cours de l'exécution nous obtenons une trace des différentes requêtes SQL effectuées par LiDO. Nous découvrons notamment la création de la table correspondant à notre classe :

CREATE TABLE c_Person ( LIDOID BIGINT NOT NULL , name VARCHAR(255) NULL , age INT NULL  )
       
      
JextCopier dans Jext
Le premier champ, un type entier intitulé LIDOID, joue le rôle d'une clé implicite, rajoutée par l'outil de définition du schéma. Les champs restants correspondent pour leur part aux propriétés de la classe. Nous remarquerons enfin que la chaîne "c_" préfixe le nom de la table. Il s'agit de la première lettre du paquetage, afin d'éviter tout conflit de nommage au sein de la source de données.

Nous pouvons à présent rédiger un programme de test qui nous servira d'une part à remplir la source de données et d'autre part à vérifier la possibilité de récupération des données. La partie la plus compliquée consiste à préparer la connexion vers la source de données. Le listing 2 présent les quelques lignes de code, spécifiques à notre exemple, que nous utiliserons. Ce code source crée une instance de la fabrique PersistenceManagerFactory, à laquelle nous passons certaines propriétés permettant d'identifier la source et de s'y connecter avec succès. Cet exemple utilise non seulement une collection de propriétés, mais également des mutateurs de la classe. Nous aurions pu utiliser uniquement des propriétés et, notamment, toutes les charger depuis le fichier lido_mysql.properties déjà étudié. Cette instance fournit un gestionnaire de données adapté à la source considérée, représenté par une instance de la classe PersistentManager. Notre programme utilisera ce dernier pour activer la persistance des données. Ce même gestionnaire nous donne accès à la transaction courante, fonctionnant sur le même principe que les transactions SQL. L'extrait suivant expose la marche à suivre pour dupliquer un objet Perso dans la source de données :

tx.begin();
Person person = new Person("Paul", 24);
pm.makePersistent(person);
tx.commit();
       
      
JextCopier dans Jext
La simplicité de JDO ne peut que séduire. Bien sûr, le stockage à proprement parler ne se voit réalisé qu'après invocation de la méthode commit() de l'objet Transaction. Une fois un objet présent dans la source de donnée, nous pouvons le récupérer grâce à son identificateur. Une manière simple de le faire consiste à obtenir ce dernier juste après l'appel de makePersistent() :

Obejct objID = pm.getObjectId(person);
tx.begin();
person = (Person) pm.getObjectById(paulId, true);
String name = person.getName();            
System.out.println("Nom de Person = " + name);
tx.commit();
       
      
JextCopier dans Jext
L'obtention d'un objet persisté a lieu par l'entremise de la méthode getObjectById(). Son second paramètre, un booléen, permet d'effectuer une validation de l'objet. En effet, JDO emploie un cache, et nous ne sommes pas assurés de la validité des objets de ce cache par rapport au contenu de la source de donnée. En mettant ce paramètre à vrai, nous obligeons JDO à comparer son cache à la source de données et à le mettre à jour si besoin est. Les différentes subtilités inhérentes à son utilisation, dans des cas particulier, sont clairement énumérées dans la documentation de l'API JDO.


 Requêtes

Dans la pratique, l'obtention d'un objet à l'aide de son identificateur ne possède que peu d'intérêt. Fort heureusement, la spécification de Sun Microsystems prévoit la gestion de requêtes, similaires au SQL. Dans l'exemple proposé par le listing 3, nous récupérons les données stockées dans la source par l'entremise d'une requête JDO.

La création de la requête nécessite la spécification de la classe concernée par la recherche, c'est pourquoi nous passons en paramètre à newQuery() l'attribut class de Person. Nous pouvons ensuite appliquer un filtre pour limiter les résultats, présentés sous forme d'une Collection Java. La réalisation d'une requête dont le filtre reste vide équivaut à demander toutes les instances d'une classe.

L'exemple présenté repose sur la syntaxe JDOQL, qui n'est autre que du Java. Nous effectuons ici une requête récupérant toutes les personnes dont le nom commence par la lettre P. L'intérêt évident de ce langage de requête réside dans sa formidable homogénéité avec son langage d'encapsulation, Java. JDOQL apporte toutefois certaines nouveautés, comme la comparaison de dates ou de chaînes par l'intermédiaire des opérateurs classiques d'infériorité, supériorité et égalité.

Les requêtes JDOQL supporte également les paramètres. Ainsi, le code suivant installe un paramètre nommé "name" auquel nous faisons référence dans la requête. Lors de l'appel de la méthode execute() nous devons fournir la valeur des différents paramètres :

query.declareParameters("String name");
String filter = "this.name == name"; 
Collection persons = (Collection) query.execute("Paul");
       
      
JextCopier dans Jext | Jext | Plugin Codegeek

 Gestion de l'aggrégation et de la composition

L'exemple étudié ne reflète que pauvrement la réalité des systèmes d'information. Nous allons donc l'étoffer en introduisant les notions d'aggréation et de composition. Pour cette dernière, nous modifions la classe Person et lui ajoutons deux membres permettant de spécifier l'adresse d'une personne et ses qualification professionnelles. Puisqu'une adresse appartient à une seule personne, nous allons encapsuler la classe Address, par composition, dans Person. Plutôt que d'étendre les champs cette dernière, nous définirons l'encapsulation comme un nouveau champ, qui accueillera une version sérialisée de l'objet. Le listing 4 décrit la classe Address. Vous constaterez que celle-ci implémente l'interface java.io.Serializable, pour permettre à la source de données de la stocker, dans notre cas, au sein d'un champ BLOB de la table c_Person. La mise en place de la composition nécessite de modifier sensiblement le fichier metadata.jdo :

<class name="Person">
  <field name="address" embedded="true"/>
</class>
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
L'élément autorise l'activation de la persistance d'une instance de la classe Addess, le membre d'instance "address" de Person. Gardez bien à l'esprit que la persistance n'est effective que dans ce cas précis, un objet Address seul ne pourra pas bénéficier du procédé de stockage.

Nous introduisons l'aggrégation grâce à une référence vers la classe Skills dans Person. Contrairement à Address, nous ne ferons pas appel à la sérialisation et opterons pour une déclaration de persistance normale dans le cadre de JDO. Le listing 5 présente la classe Skills dont la définition de persistance au sein de metadata.jdo prend la forme suivante :

<class name="Skills" />
       
      
JextCopier dans Jext
En examinant les traces émises par LiDO au cours de l'exécution du procédé de définition des schémas, nous pouvons observer les lignes suivantes :

CREATE TABLE c_Person ( LIDOID BIGINT NOT NULL , address LONGBLOB NULL ,
                                    name VARCHAR(255) NULL , age INT NULL ,
                                    level BIGINT NULL  )
CREATE TABLE c_Skills ( LIDOID BIGINT NOT NULL , diploma VARCHAR(255) NULL  )
       
      
JextCopier dans Jext
La différence entre une composition (réalisée par l'élément dont l'attribut embedded vaut vrai) et une aggrégation apparaît clairement : la classe Skills possède sa propre table, au contraire de Address. Pour récupérer toutes les informations relatives à une personne, nous devons réaliser une jointure entre les tables c_Person et c_Skills, ce que permet le champ level de la première, correspondant à la clé LIDOID de la seconde.

Notre nouveau programme d'essai reprend la structure du premier. Néanmoins, nous devons à présent préciser les attributs adresse et qualification de notre donnée d'exemple.

person.setAddress(new Address("Adresse de Paul"));
person.setLevel(new Skills("Technicien"));
       
      
JextCopier dans Jext
Après récupération d'une instance de Person depuis la source de données, nous pouvons très facilement récupérer, toujours de manière totalement transparente, les nouveaux attributs :

Address address = person.getAddress();
Skills level = person.getLevel();
       
      
JextCopier dans Jext

 Gestion de l'héritage

L'une des difficultés que nous pouvons nous attendre à rencontrer concerne la persistance de chaînes d'héritage. Nous allons spécialiser notre exemple en créant une classe Employee, héritant de Person. Cette nouvelle entité permet d'attribuer un salaire à notre employé. Le listing 6 offre le code source complet. JDO doit maintenant savoir que notre nouvelle classe hérite de Person. Pour ce faire, nous modifions une fois de plus le fichier de méta-données et ajoutons la ligne suivante :

<class name="Employee" persistence-capable-superclass="company.Person" />
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
La gestion de l'héritage consiste à l'ajout d'un attribut persistence-capable-superclass dans l'élément class. La valeur de celui-ci doit représenter le nom complet (avec le paquetage donc) de la classe parente qui doit impérativement avoir été définie persistante pour JDO. Une fois de plus, nous pouvons examiner les requêtes SQL générées par LiDO pour bien comprendre le procédé de stockage sous-jacent :

CREATE TABLE c_Employee ( LIDOID BIGINT NOT NULL , address LONGBLOB NULL ,
                                       name VARCHAR(255) NULL , age INT NULL ,
                                       level BIGINT NULL , salaire FLOAT NULL  )
       
      
JextCopier dans Jext
Nous remarquons que la table c_Employee reprend tous les champs de c_Person et y ajoute les siens propres, ici le champ salaire. Pour les besoins de nos essais, il nous suffit de remplacer l'instance de Person par une instance d'Employee, à partir de laqulle nous vérifierons que le salaire a été corrément conservé dans la source de données.

Employee person = new Employee("Paul", 24, (float) 40000.00);
// .
float salaire = person.getSalaire();
       
      
JextCopier dans Jext

 Gestion des collections

Toujours dans le but d'adapter nos connaissances à des situations réelles, nous allons à présent aborder la gestion des collections. En considérant qu'un employé appartient à une entreprise, il va de soit que la classe Company accueillera une Collection d'employés, représentés par des instances de Employee. Nous trouverons dans le listing 7 la définition complète de notre nouvelle classe. L'interface publique de cette dernière propose le strict minimum pour la gestion des employés. Nous pouvons ainsi en ajouter à l'aide de addEmployee() et récupérer l'ensemble par l'entremise de getEmployee().

Comme à l'accoutumée, nous devons appliquer quelques modifications au fichier de méta-données, à savoir l'ajout d'un nouvel élément :

<class name="Company">
  <field name="employees">
    <extension vendor-name="libelis" key="collection-type" value="java.util.List"/>
  </field>
</class>
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Nous observons ici ce qui distingue un champ de Collection d'un autre. Nous devons impérativement qualifier celui-ci en précisant le type sélectionné. Prenez garde car, contrairement à tout ce que nous avons vu jusqu'à présent, "collection-type" désigne une extension propriétaire au standard JDO. Seule la bibliothèque LiDO autorise son emploi. Nous pouvons enfin examiner les requêtes SQL générées :

CREATE TABLE c_Company ( LIDOID BIGINT NOT NULL , name VARCHAR(255) NULL  )
CREATE TABLE c_Company_employees ( LIDOFK BIGINT NOT NULL ,
                                                      LIDOVALUE BIGINT NULL , LIDOPOS DOUBLE NULL  )
       
      
JextCopier dans Jext
A n'en pas douter, l'ajout d'une collection complique les choses. La table c_Company pour sa part ne recèle rien de spécial. Toutefois, c_Company_employee ne ressemble en rien à ce que nous avons étudié jusqu'à présent, même le familier LIDOID manquant à l'appel. En réalité, cette table fait office de table de liaison. La clé, intitulé LIDOFK pour LIDO Foreign Key, désigne une clé étrangère liée à la clé primaire LIDOID de c_Company. Les deux autres champs, LIDOPOS et LIDOVALUE, désignent respectivement la position d'un objet dans la collection et la valeur associée à cette position.

Cette fois, de plus amples modifications apparaissent dans le programme de test. Nous créons au total 3 employés que nous affectons ) une compagnie. Pour récupérer la liste de nos employés, nous conserverons trace de l'identificateur de l'instance de Company.

Company company = new Company("boite");
pm.makePersistent(company);
Object companyId = pm.getObjectId(company);
Employee person = new Employee("Paul", 24, (float) 40000.00);
company.addEmployee(person);
person = new Employee("Jean", 37, (float) 45000.00);
company.addEmployee(person);
person = new Employee("Martine", 32, (float) 48000.00);
company.addEmployee(person);
       
      
JextCopier dans Jext
Le listing 8 présente une méthode pour lister, à partir de l'identificateur de l'entreprise tous ses employés. Encore une fois, nous pouvons apprécier les facilités offertes par les Java Data Objects. Nous allons pour terminer effectuer une recherche plus complexe qui recherche un employé précis au sein d'une entreprise donnée. Vous pourrez vous reporter au listing 9 pour lire le code source correspondant.

Outre l'habituelle syntaxe Java pour mener la recherche, nous pouvons remarquer la déclaration de deux paramètres de requêtes, compName et empName. Ceux-ci permettent de spécifier l'entreprise et le nom de l'employé. En sus, nous déclarons une variable de requête par le biais de l'instruction query.declareVariables(). Lors de la recherche, LiDO va réaliser une jointure entre les tables c_Company et c_Company_employee pour automatiquement assigner à notre variable la valeur de chaque employé de la collection. Nous demandons explicitement cette liaison lors de l'invocation de l'instruction de filtre contains().


 Conclusion

La spécification JDO, activement soutenue par Sun, permet de faire persister des objets Java sur différents supports et de manière transparente pour l'utilisateur. En outre, celui-ci ne manipule que du Java et ne doit plus s'imprégner de langages de requêtes particuliers. En modifiant quelques paramètres dans un fichier de propriétés, l'auteur d'une application peur la faire migrer vers un tout autre support sans jamais modifier le code source. Les applications JDO s'intègrent donc parfaitement dans différents environnements Java, aussi bien dans les applications classiques que dans les applications J2EE. La gestion de cache offerte par les différentes implémentations autorise souvent des performances très supérieures aux bases de données relationnelles courantes utilisées seules. Le facteur couramment constaté est de 1 pour 10, mais peut se révéler plus important.

Grâce à sa faible empreinte mémoire, elle peut fonctionner là où aucune autre solution de persistance à haute performance n'est possible comme dans les environnements embarqués. On devine toutefois, suivant le vieil adage que plus c'est simple à utiliser côté client plus c'est sophistiqué côté serveur, qu'il s'agit d'une technologie de pointe ultra-sophistiquée, probablement du top-niveau du génie logiciel à l'heure actuelle.


 Annexes

Bibliographie : Java Data Objects, de Robin M. Roos, chez Addison Wesley

Sites Internet : Spécification JDO de Sun (http://java.sun.com/products/jdo/), LiDO de LIBeLIS (), TJDO (), OJB (), JDO Central (http://www.jdocentral.com/)

package company;

public class Person {
  private String name;
  private int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Properties prop = new Properties();
prop.put("javax.jdo.PersistenceManagerFactoryClass",
            "com.libelis.lido.PersistenceManagerFactory");
      
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(prop);
pmf.setConnectionDriverName("org.gjt.mm.mysql.Driver");
pmf.setConnectionURL("jdbc:mysql://localhsot/test");
pmf.setConnectionUserName("root");

PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
       
      
JextCopier dans Jext
System.out.println("Récupération de l'objet \"Paul\" par Query");
Query query = pm.newQuery(Person.class);
String filter = "name.startsWith(\"P\")";
query.setFilter(filter);
Collection persons = (Collection) query.execute();
Iterator it = persons.iterator();
while (it.hasNext()) {
  person = (Person) it.next();
  String name = person.getName();
  System.out.println("Nom de Person = " + name);
}
       
      
JextCopier dans Jext
package company;

public class Address implements java.io.Serializable {
  private String coordinates;

  public Address(String coordinates) {
    this.coordinates = coordinates;
  }

  public String getCoordinates() {
    return coordinates;
  }

  public void setCoordinates(String coordinates) {
    this.coordinates = coordinates;
  }

  public String toString() {
    return "[Address] coordinates = " + coordinates;
  }
}
       
      
JextCopier dans Jext
package company;

public class Skills {
  private String diploma;

  public Skills(String diploma) {
    this.diploma = diploma;
  }

  public String getDiploma() {
    return diploma;
  }

  public void setDiploma(String diploma) {
    this.diploma = diploma;
  }
}
       
      
JextCopier dans Jext
package company;

public class Employee extends Person {
  private float salaire;

  public Employee(String name, int age, float salaire) {
    super(name, age);
    this.salaire = salaire;
  }

  public float getSalaire() {
    return salaire;
  }

  public void setSalaire(float salaire) {
    this.salaire = salaire;
  }
}
       
      
JextCopier dans Jext
public class Company {
  String name;
  private List employees = new ArrayList();

  public Company(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List getEmployees() {
    return employees;
  }

  public void addEmployee(Employee employee) {
    employees.add(employee);
  }
}
       
      
JextCopier dans Jext
company = (Company) pm.getObjectById(companyId, true); 
List employees = (ArrayList) company.getEmployees();
Iterator it = employees.iterator();
while (it.hasNext())
{
  Employee person = (Employee)it.next();
  String name = person.getName();
  Address address = person.getAddress();
  Skills level = person.getLevel();
  float salaire = person.getSalaire();
  // ...
}
       
      
JextCopier dans Jext
Query query = pm.newQuery(Company.class);
query.declareParameters("String compName, String empName");
query.declareVariables("Employee emp");
String filter = "(name == compName) &&
                   (employees.contains(emp) &&
                    emp.name == empName)"; 
query.setFilter(filter);

Collection companies = (Collection) query.execute("boite", "Paul");
Iterator it = companies.iterator();
while (it.hasNext())
{
  company = (Company)it.next();
  List employees = (ArrayList)company.getEmployees();
  Iterator it = employees.iterator();

  while (it.hasNext())
  {
    Employee person = (Employee)it.next();
    // ...
  }
}
       
      
JextCopier dans Jext


par Romain Guy
romain.guy@jext.org
http://www.jext.org
Dernière mise à jour : 14/10/2006


Précédent  
  Java  
  Suivant

 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE