Disseny de la persistència JDO i frameworks de persistència

Slides:



Advertisements
Presentaciones similares
Enginyeria del SW II: Disseny de la persistència. JDO Disseny de la persistència JDO i frameworks de persistència Toni Navarrete Enginyeria del Software.
Advertisements

Serialització i persistència
Cambios en el espacio: transformaciones geométricas
Impress 3... Posa-hi un fons!
Campus Virtual.
Campus Virtual.
Projecte Fi de Carrera Disseny i desenvolupament d’un esquema criptogràfic per gestionar de forma segura els historials mèdics dels pacients a través d’una.
ORIENTACIÓ I COORDENADES GEOGRÀFIQUES
Tema 6: L’ENERGIA.
Disseny de la persistència Hibernate i frameworks de persistència POJO
MÚLTIPLES I DIVISORS.
EL LLENGUATGE MUSICAL.
Disseny de la interfície d’un smartwatch i l’aplicació mòbil
Ciències per al món contemporani
FUNCIONS ELEMENTALS.
Tema 2. DIVISIBILITAT.
MESCLES I DISSOLUCIONS
Introducció de TEDIs (COACs) Versió 4.0
El mercat ELS NENS I NENES DE P-4.
Present and past simple
TERMOREGULACIÓ HORÀRIA INDIVIDUAL DELS ESPAIS DEL CENTRE
PETITS REPORTERS Títol.
Disseny de la persistència Hibernate i frameworks de persistència POJO
Library and Information Science Abstract
Creació d’un mapa personalitzat
Resolució de problemes algebraics
Funcionament See Thecnical.
SISTEMA GESTOR D’EMPRESA D’EXCAVACIONS
Potències de nombres racionals
POLINOMIS.
TÈCNIQUES D’ESTUDI.
Tutorials Campus Virtual Càrrega automàtica d’alumnes
Com introduir les Guies Docents
1. L’empirisme de Locke 1.3. L’anàlisi dels conceptes de la metafísica escolàstica Pàgina 258 Els dos sentits de la substància: com a substrat i com a.
WEBQUEST WEB...QUÈ ? Alumnes de l’Escola ESTEL VALLSECA.
Enginyeria del software II
Problema 1: Trobar la recta que passa pel punts A(2, -3) i B(-1, 3)
Disseny de la persistència Serialització
Curs de Llenguatge Administratiu Valencià Juli Martínez Amorós
Framework MVC en PHP Autor: Josep Humet Alsius
Jonathan Ceballos Rodriguez ( ) Zenón Perisé Alía ( )
Tema 5: Nombres naturals i enters
Optimització de consultes en MySQL (unes notes)
Disseny de la persistència Introducció i mapping objecte/relacional
Disseny de la persistència Introducció i mapping objecte/relacional
Aplicacions web bàsiques Introducció a servlets i JSP
Disseny de la persistència Serialització
Estructurant les aplicacions MVC JSTL Struts
L’electricitat i el circuit elèctric
Problemes que es poden resoldre amb equacions
Les taules de multiplicar
La imatge corporativa Una eina fonamental en l’actualitat
REAXYS.
Passes a seguir per iniciar un nou curs acadèmic en el GestIB
Threads en Java David Gañán Jiménez.
Jessica, Gerard, Laura P, Alex
Projecte Fi de Carrera - J2EE Alumne: Daniel Clemente Marcè
LA NOVA SELECTIVITAT I L’ACCÉS A LA UNIVERSITAT
La literatura i les matemàtiques van de la mà.
BASES DE DADES Consultes
SISTEMA DUNAR.
Sistema de descàrrega d’aplicacions per a mòbils intel·ligents
Propostes de millora en el GIR
NO TINGUIS POR, QUE JO SÓC AMB TU
CONCURS BÍBLIC NOM: CÉSAR COGNOMS: GARCÍA MEDINA GRUP B DATA NAIXAMENT: 02/07/2003 COL·LEGI: SANT JOSEP OBRER CARRER: COVADONGA S/N
Projecte: Videojocs.cat
6a SETMANA de QUARESMA US PRESENTEM LA JOANA QUE ENS ACOMPANYARÀ EN AQUESTA SISENA SETMANA DE QUARESMA. LA JOANA DE VEGADES ES MOSTRA MOLT RESPONSABLE.
LES MÀQUINES.
Estils i Plantilles Ms Word.
WebQuest “ L’esport, ha de ser violent? ”.
Transcripción de la presentación:

Disseny de la persistència JDO i frameworks de persistència Toni Navarrete Enginyeria del Software II – UPF 2005

Recordatori: problemes (i aventatges) d’altres solucions Serialitzatió Avantantges: Estàndard en qualsevol ambient Java Fàcil d’utilitzar El model de dades és directament el de les classes (aprofita OO) Inconvenients: No té les característiques d’un gestor de BD robust Per exemple, índexs, transaccions,... No és escalable

Recordatori: problemes (i aventatges) d’altres solucions JDBC Dóna accés a SQL Usa el model relacional de SQL No el model orientat a objectes de Java Procedimental en lloc d’OO El processament de dades es fa mitjançant SQL i no Java Les operacions són expressades en relació a taules, files i columnes SQL no està realment estandaritzat, amb la qual cosa la portabilitat no sempre és real

Recordatori: problemes (i aventatges) d’altres solucions Quan s’utilitza JDBC, el programador està obligat a treballar amb dos models de dades diferents, així com amb dos paradigmes i llenguatges d’accés a les dades distints. El resultat sol ser que s’escriu codi Java procedural per manipular les taules. No OO

Conseqüència Moltes organitzacions comencen a desenvolupar el seu propi framework per a persistència i O/R mapping, que permeti els seus objectes interactuar amb la BD de forma transparent Exemples Castor Apache ObJectRelationalBridge (OJB) ODMG 3.0, desenvolupat pel Object Data Management Group (ODMG). Inicalment en C++ i Smaltalk, ha estat una de les bases de JDO i n’és un subconjunt

Problemes (i avantatges) d’altres solucions ORM propietaris (Object-Relational Mapping) Riscos significatius a l’hora de desenvolupar un ORM propi Limitacions d’APIs ORM propietàries. Adoptar un API propietària és sempre arriscat. A moltes implementacions: Falta d’encapsulació causada per la necessitat de definir mètodes getter i setter públics per als atributs persistents Extensibilitat limitada per la falta de soport de l’herència Falta de soport de referències polimòrfiques Dependència absoluta d’un venedor

JDO És una nova iniciativa de la comunitat Java per crear un framework estandaritzat per a persistència (de la mateixa que Swing ho és per a interfície gràfica) JDO és només una especificació, de la qual els fabricants de software faran implementacions (a vegades lliures, a vegades no) Normalment parlarem de JDO per accedir a BDR, però pot ser qualsevol forma d’emmagatzemantge permanent (XML, fitxers,...) Sun produeix el JDORI (JDO Reference Implementation) com a una implementació per demostrar que l’especificació és vàlida. Però no està pensada per explotació en entorns reals

JDO JDO: capacitats de BD de JDBC amb la integració Java de la serialització JDO usa el model d’objectes Java Les instàncies tenen un identificador únic (OID únic) Soporta transaccions Emmagatzemar instàncies, recuperar-les i modificar-es és transparent Resum: mínima intrusió i màxima transparència

Comparació JDO amb les altres alternatives EJB també defineix un mecanisme de persistència transparent (Container Managed Persistence, CMP), però EJB és una arquitectura complexa i amb més overhead que JDO Serialització també és OO però no és apte per treballar amb grans volums de dades, no és escalable, i no té suport per índexs, transaccions i demés mecanismes d’un SGBD

JDO no substituirà JDBC JDO i JDBC JDO no substituirà JDBC Són complementàries Les implementacions de JDO solen utilitzar JDBC per sota per connectar-se a la BD JDBC és útil per gestionar connexions amb la BD JDBC és força sòlid JDBC està soportat per la majoria de fabricants de SGBC

JDO JDOcentral.com: A comparion between Java Data Objects (JDO), Serialization and JDBC for Java Persistance

Exemple d’una petita aplicació JDO amb la JDORI

Exemple d’una classe persistent amb JDO package es2; public class Persona { String nom, cognom; int anyNaixement = 0; public Persona() {} // a JDO és obligatori que hi hagi un constructor sense arguments public Persona(String nom, String cognom, int anyNaixement) { this.nom = nom; this.cognom = cognom; this. anyNaixement = anyNaixement; } public void setNom(String nom) { public String getNom() { return this.nom; public void setCognom(String cognom) { public String getCognom() { return this.cognom; public void setAnyNaixement(int anyNaixement) { public int getAnyNaixement() { return this.anyNaixement;

Declaració de classes persistents L’únic requeriment és que la classe ha de tenir un constructor sense arguments Ara podem crear instàncies d’aquesta classe Person i guardar-las a la BDR JDO utilitza un fitxer de metadades per dir quines classes seran persistents i reflectir tota la informació relacionada amb la persistència (ho veurem amb més detall més endavant) Fitxer amb extensió .jdo

Exemple de fitxer de metadades (es2.jdo) <?xml version= "1.0" encoding="UTF-8"?> <!DOCTYPE jdo SYSTEM "file:/C:/.../jdori-1_0/srcjavax/jdo/jdo.dtd"> <jdo> <package name= "es2" > <class name="Persona" /> </package> </jdo> o <!DOCTYPE jdo PUBLIC “-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 1.0//EN" "http://java.sun.com/dtd/jdo_1_0.dtd"> Nota: algunes implementacions fixen com s’ha d’anomenar el fitxer de metadades

Jars necessaris JDO es pot baixar de www.jcp.org (JSR-12) Per treballar amb la implementació de referència: jdo.jar Les interfícies estàndard i les classes definides a l’especificació JDO jdori.jar La implementació de referència de Sun btree.jar Implementa un petit gestor d’emmagatzament per la JDORI de Sun jta.tar Java Transaction API que usa JDO per definir transaccions antlr.jar Serveix per parsejar el llenguatges de consultes de JDO xerces.jar Per parsejar XML

Enhancement Un cop que hem compilat la(s) classe(s), hem de fer un enhancement Això sobre-escriu els fitxers de bytecode (.class) afegint dades i mètodes que permeten les instàncies de la classe ser manegades per la implementació JDO Ho fa a partir del fitxer de metadades Cada fabricant de JDO pot incloure el seu enhancer, però suposadament són compatibles JDORI porta el reference enhancer

Enhancement

Enhancement

Enhancement java com.sun.jdori.enhancer.Main es2.jdo es2/Persona.class Algunes opcions: -v (verbose) -d (a un directori distint, sense sobreescriure el .class original): java com.sun.jdori.enhancer.Main -v -d enhanced es2.jdo es2/Persona.class Cada fabricant d’implementacions JDO té el seu enhancer que es crida de forma diferent Noteu que l’enhancement és independent del magatzem de dades que utilitzem després

Fent una aplicació Ara farem una aplicació que crea instàncies de Persona i les guarda a una BD JDORI porta un petit gestor com a referència que es diu FOStore (File Object Store)

Estructura de classes de JDO El nucli de JDO és la interfície PersistenceManager, que és la que manega la connexió amb un magatzem de dades

Estructura de classes de JDO Per obtenir i configurar un PersistenceManager es fa mitjançant la interfície PersistenceManagerFactory A la vegada, el PersistenceManagerFactory s’obté a partir d’un mètode estàtic de la classe JDOHelper, segons unes propietats (url de connexió, login, password i el nom de la implementació de JDO que utilitzem)

Estructura de classes de JDO Exemple de propietats per crear un PersistenceManagerFactory: javax.jdo.PersistenceManagerFactoryClass=com.sun.jdori.fostore.FOStorePMF javax.jdo.option.ConnectionURL =fostore:database/fostoredb javax.jdo.option.ConnectionUserName=toni javax.jdo.option.ConnectionPassword=toni Aquestes propietats poden estar a un fitxer (típicament jdo.properties) o ser configurades des de programa

Estructura de classes de JDO Un PersistenceManager té associat una instància de la interfície JDO Transaction, per a controlar el començament i finalització d’una transacció Per obtenir la instància de Transaction ho fem amb el mètode currentTransaction de la instància de PersistenceManager En JDO tota acció que hagi de modificar la BD estarà emmarcada dins d’una transacció Usarem els mètodes begin, commit i rollback de la instància de Transaction

FOStore JDORI porta un petit gestor com a referència que es diu FOStore (File Object Store) Anem a crear una BD per guardar les futures instàncies de la classe Persones jdo.properties Directori database CreateDatabase.java

Creació d’una BD en FOStore package es2; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; public class CreateDatabase{ public static void main(String[] args){ create(); } public static void create(){ try{ InputStream propertyStream = new FileInputStream("es2/jdo.properties"); Properties jdoproperties = new Properties(); jdoproperties.load(propertyStream); jdoproperties.put("com.sun.jdori.option.ConnectionCreate","true"); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties); PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); tx.begin(); tx.commit(); } catch (Exception e) { System.err.println("Exception creating db"); e.printStackTrace(); System.exit(-1); Aquest codi crea un magatzem al directori database Propietat com.sun.jdori.option.ConnectionCreate a true

Creant l’aplicació package es2; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import java.util.Map; import java.util.HashMap; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; public class Aplicacio1{ protected PersistenceManagerFactory pmf; protected PersistenceManager pm; protected Transaction tx; public Aplicacio1() { try{ InputStream propertyStream = new FileInputStream("es2/jdo.properties"); Properties jdoproperties = new Properties(); jdoproperties.load(propertyStream); pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); } catch (Exception e) { System.err.println("Exception creating db"); e.printStackTrace(); System.exit(-1); } public void executeTransaction() { tx.begin(); Persona p = new Persona("toni","navarrete",1973); pm.makePersistent(p); tx.commit(); } catch (Throwable exception){ exception.printStackTrace(System.err); if (tx.isActive()) tx.rollback(); public static void main(String[] args) { Aplicacio1 ap = new Aplicacio1(); ap.executeTransaction(); Creant l’aplicació

També es poden especificar les propietats dins del codi: Sobre les propietats També es poden especificar les propietats dins del codi: ... Properties props = new Properties(); props.setProperty("javax.jdo.PersistenceManagerFactoryClass", "com.sun.jdori.fostore.FOStorePMF "); props.setProperty("javax.jdo.option.ConnectionURL", "fostore:database/fostoredb"); props.setProperty("javax.jdo.option.ConnectionUserName",“toni"); props.setProperty("javax.jdo.option.ConnectionPassword",“toni"); props.setProperty("javax.jdo.option.Optimistic",“false"); pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties);

Creant l’aplicació amb una millor organització package es2; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; public abstract class Aplicacio{ protected PersistenceManagerFactory pmf; protected PersistenceManager pm; protected Transaction tx; public abstract void execute(); public Aplicacio() { try{ InputStream propertyStream = new FileInputStream("es2/jdo.properties"); Properties jdoproperties = new Properties(); jdoproperties.load(propertyStream); pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); } catch (Exception e) { System.err.println("Exception creating db"); e.printStackTrace(); System.exit(-1); } public void executeTransaction() { tx.begin(); execute(); tx.commit(); } catch (Throwable exception){ exception.printStackTrace(System.err); if (tx.isActive()) tx.rollback(); Creant l’aplicació amb una millor organització package es2; public class CrearPersones extends Aplicacio{ public static void main(String[] args) { CrearPersones cp = new CrearPersones(); cp.executeTransaction(); } public void execute() { Persona p1 = new Persona("pasqual","maragall",1950); pm.makePersistent(p1); Persona p2 = new Persona("artur","mas",1955); pm.makePersistent(p2);

Mètode getExtent del PersistenceManager Consultes Extent és una interfície que permet accedir a totes les instàncies d’una classe persistent Mètode getExtent del PersistenceManager Extent extent = pm.getExtent(Persona.class,false); /* el segon paràmetre indica si també considerar les instàncies de les subclasses */

Consulta de totes les persones emmagatzemades package es2; import java.util.Iterator; import javax.jdo.Extent; public class LlistatPersones extends Aplicacio{ public static void main(String[] args) { LlistatPersones lp = new LlistatPersones(); lp.executeTransaction(); } public void execute() { Extent extent = pm.getExtent(Persona.class,false); Iterator it = extent.iterator(); while (it.hasNext()) { Persona p = (Persona)it.next(); System.out.println("Nom: " + p.getNom()); System.out.println("Cognom: " + p.getCognom()); System.out.println("Any naixement: " + p.getAnyNaixement()); System.out.println(); extent.close(it); Consulta de totes les persones emmagatzemades

Consulta de totes les persones emmagatzemades (sense transacció) package es2; import java.util.Iterator; import javax.jdo.Extent; public class LlistatPersones extends Aplicacio{ public static void main(String[] args) { LlistatPersones lp = new LlistatPersones(); lp.consulta(); } public void consulta() { Extent extent = pm.getExtent(Persona.class,false); Iterator it = extent.iterator(); while (it.hasNext()) { Persona p = (Persona)it.next(); System.out.println("Nom: " + p.getNom()); System.out.println("Cognom: " + p.getCognom()); System.out.println("Any naixement: " + p.getAnyNaixement()); System.out.println(); extent.close(it); public void execute() {} Consulta de totes les persones emmagatzemades (sense transacció)

Consultes i filtres La interfície Query permet definir filtres sobre un Extent, per fer consultes més específiques (i no de tots els elements) Quan es crea una Query s’especifica l’Extent i la condició: Query q = pm.newQuery(extent,"nom == nomPersona"); q.declareParameters("String nomPersona"); També es pot crear la Query directament sobre la classe: Query q = pm.newQuery(Persona.class,"nom==\"toni\""); En especificar la condició podem utilitzar els operadors comparatius, aritmètics,... de Java

Consulta del cognom d’una persona concreta package es2; import java.util.Iterator; import java.util.Collection; import javax.jdo.Extent; import javax.jdo.Query; public class CognomPersona extends Aplicacio{ public static void main(String[] args) { CognomPersona cp = new CognomPersona(); cp.executeTransaction(); } public void execute() { Extent extent = pm.getExtent(Persona.class,false); String nomPersona = new String("toni"); Query q = pm.newQuery(extent,"nom == nomPers"); q.declareParameters("String nomPers"); Collection result = (Collection)q.execute(nomPersona); Iterator it = result.iterator(); if (it.hasNext()) { Persona p = (Persona)it.next(); System.out.println("Nom: " + p.getNom()); System.out.println("Cognom: " + p.getCognom()); System.out.println("Any naixement: " + p.getAnyNaixement()); q.close(result); Consulta del cognom d’una persona concreta

Més coses Treballar amb un gestor de veritat Una altra implementació de JDO: JPOX És opensource i té suport per treballar amb nombrosos SGBDs (MySQL, PostgreSQL i Oracle entre d’altres) Des de la versió 1.1 suporta JDO 2.0 i de fet n’és la nova implementació de referència Associacions entre classes (relacions entre taules) i herència Generació automàtica de l’esquema de la BD Capacitat per configurar el mapping objecte/relacional a l’hora de crear les taules Permet: Insercions, eliminacions i modificacions d’objectes Consultes Persistència transitiva

Un exemple més complet (amb JPOX) Persona Grup 0..* 0..1 Empleat

Persona package es2; public class Persona { String nom, cognom; int anyNaixement = 0; Grup grupp; public Persona() {} // a JDO és obligatori que hi hagi un constructor sense arguments public Persona(String nom, String cognom, int anyNaixement) { this.nom = nom; this.cognom = cognom; this. anyNaixement = anyNaixement; } public void setNom(String nom) { this.nom = nom; } public String getNom() { return this.nom; } public void setCognom(String cognom) { this.cognom = cognom; } public String getCognom() { return this.cognom; } public void setAnyNaixement(int anyNaixement) { this. anyNaixement = anyNaixement; } public int getAnyNaixement() { return this.anyNaixement; } public void setGrup(Grup g) { this.grupp = g; } public Grup getGrup() { return this.grupp;

Grup Suporta diversos tipus per a les col·leccions: Collection Set package es2; import java.util.*; public class Grup { String nom; Set persones; public Grup() {} // a JDO és obligatori que hi hagi un constructor sense arguments public Grup(String nom) { this.nom=nom; this.persones=new HashSet(); } public void setNom(String nom) { this.nom = nom; public String getNom() { return this.nom; public void afegeixPersona(Persona p) { this.persones.add(p); p.setGrup(this); public Set getPersones() { return this.persones; Suporta diversos tipus per a les col·leccions: Collection Set HashSet Map List ArrayList HashMap Hashtable LinkedList TreeMap TreeSet Vector

Empleat package es2; public class Empleat extends Persona{ int salari; public Empleat() {} // a JDO és obligatori que hi hagi un constructor sense arguments public Empleat(String nom, String cognom, int anyNaixement, int salari) { this.nom = nom; this.cognom = cognom; this.anyNaixement = anyNaixement; this.salari=salari; } public void setSalari(int salari) this.salari = salari; public int getSalari() return this.salari; Empleat

Fitxer de metadades (package.jdo) <?xml version="1.0"?> <!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 1.0//EN" "http://java.sun.com/dtd/jdo_1_0.dtd"> <jdo> <package name="es2"> <class name="Persona"> <field name="grupp" persistence-modifier="persistent" /> </class> <class name="Empleat" persistence-capable-superclass="es2.Persona"/> <class name="Grup"> <field name="persones" mapped-by="grupp"> <collection element-type="es2.Persona"/> </field> </package> </jdo> Comanda d’Enhancement: java -cp "build;lib/jpox.jar;lib/jpox-enhancer.jar;lib/bcel.jar;lib/jdo.jar; lib/log4j.jar" org.jpox.enhancer.JPOXEnhancer build/es2/package.jdo NOTA: aquest fitxer de metadades és per a JDO 1 (JPOX 1.0). Més endavant es veurà com definir l’herència de forma precisa per a JDO 2 (JPOX 1.1)

Extensions als elements de metadades Els fabricants d’implementacions JDO poden crear les seves extensions als elements del fitxers de metadades Lògicament no seran portables a altres implementacions Es poden definir paràmetres referents a com emmagatzemar les dades, com per exemple crear índexs, definir primary-keys, especificar longituds de strings,... Exemple: <field name="name"> <extension vendor-name="jpox“ key="length" value="max 100"/> </field> JDO 2.0 ja integra moltes d’aquestes extensions de forma estàndard. Per exemple <field name=“name" persistence-modifier="persistent"> <column length=“100" jdbc-type="VARCHAR"/>

Tractament de les relacions. Relacions 1 a 1 Single-ended <package name="mydomain"> <class name="User" identity-type="datastore"> <field name="login" persistence-modifier="persistent"> <column length=“20" jdbc-type="VARCHAR"/> </field> </class> <class name="Account" identity-type="datastore"> <field name="firstName" persistence-modifier="persistent"> <column length=“50" jdbc-type="VARCHAR"/> <field name="secondName" persistence-modifier="persistent"> <field name="user" persistence-modifier="persistent"> </package>

Tractament de les relacions. Relacions 1 a 1 Double-ended <package name="mydomain"> <class name="User" identity-type="datastore"> <field name="login" persistence-modifier="persistent"> <column length=“20" jdbc-type="VARCHAR"/> </field> <field name="account" persistence-modifier="persistent"> </class> <class name="Account" identity-type="datastore"> <field name="firstName" persistence-modifier="persistent"> <column length=“50" jdbc-type="VARCHAR"/> </field> <field name="secondName" persistence-modifier="persistent"> <column length=“50" jdbc-type="VARCHAR"/> <field name="user" persistence-modifier="persistent"> </package>

Tractament de les relacions. Relacions 1 a N Unidireccional amb foreign key: <package name="mydomain"> <class name="Account" identity-type="datastore"> <field name="firstName" persistence-modifier="persistent"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="lastName" persistence-modifier="persistent"> <field name="addresses" persistence-modifier="persistent"> <collection element-type=" mydomain.Address"/> </class> <class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> <field name="street" persistence-modifier="persistent"> </package>

Tractament de les relacions. Relacions 1 a N Bidireccional amb foreign key: <package name="mydomain"> <class name="Account" identity-type="datastore"> <field name="firstName" persistence-modifier="persistent"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="lastName" persistence-modifier="persistent"> <field name="addresses" persistence-modifier="persistent" mapped-by="account"> <collection element-type=“mydomain.Address"/> </class> <class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> <field name="street" persistence-modifier="persistent"> <field name="account" persistence-modifier="persistent"> </package>

Tractament de les relacions. Relacions 1 a N En els dos cassos es pot especificar que s’utilitzi una taula per al join <package name="mydomain"> <class name="Account" identity-type="datastore"> <field name="firstName" persistence-modifier="persistent"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="lastName" persistence-modifier="persistent"> <field name="addresses" persistence-modifier="persistent"> <collection element-type=" mydomain.Address"/> <join/> </class> <class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> <field name="street" persistence-modifier="persistent"> </package>

Tractament de les relacions. Relacions M a N Amb dues taules de join (amb Set): <package name="mydomain"> <class name="Product" identity-type="datastore"> <field name="name" persistence-modifier="persistent"> <column length=“50" jdbc-type="VARCHAR"/> </field> <field name="price" persistence-modifier="persistent"> <field name="suppliers" persistence-modifier="persistent"> <collection element-type="mydomain.Supplier"> <collection/> </class> <class name="Supplier" identity-type="datastore"> <column length=“100" jdbc-type="VARCHAR"/> <field name="products" persistence-modifier="persistent"> <collection element-type="mydomain.Product"> </package>

Tractament de les relacions. Relacions M a N Amb només una taula de join (amb Set): <package name="mydomain"> <class name="Product" identity-type="datastore"> <field name="name" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> <field name="price" persistence-modifier="persistent"> <field name="suppliers" persistence-modifier="persistent" table="PRODUCTS_SUPPLIERS"> <collection element-type="mydomain.Supplier"/> <join> <column name="PRODUCT_ID"/> </join> <element> <column name="SUPPLIER_ID"/> </element> </class> <class name="Supplier" identity-type="datastore"> <column length="100" jdbc-type="VARCHAR"/> <field name="products" persistence-modifier="persistent" mapped-by="suppliers"> <collection element-type="mydomain.Product"/> </package>

Tractament de l’herència També es pot configurar quina de les 3 estratègies que es van veure al tema “Disseny de la persistència. Introducció i mapping objecte/relacional” s’utilitzarà (només des de JDO 2.0) Exemple:

Estratègia new-table (per defecte) <package name="store"> <class name="AbstractProduct"> <inheritance strategy="new-table"/> </class> <class name="Product" persistence-capable-superclass="store.AbstractProduct"> <class name="Book" persistence-capable-superclass="store.Product"> <class name="TravelGuide" persistence-capable-superclass="store.Book"> <class name="CompactDisc" persistence-capable-superclass="store.Product">

Estratègia subclass-table … <class name="AbstractProduct"> <inheritance strategy="subclass-table"/> </class> NOTA: Please note that JPOX doesn't currently support the use of classes defined with subclass-table strategy as being either the container end of a 1-N relationship, nor of such classes being the "element-type" in a 1-N relationship.

Estratègia superclass-table … <class name="Product"> <inheritance strategy="new-table"> <discriminator strategy="class-name"> <column name="PRODUCT_TYPE"/> </discriminator> </inheritance> </class> <class name="Book" persistence-capable-superclass="store.Product"> <inheritance strategy="superclass-table"/> <class name="TravelGuide" persistence-capable-superclass="store.Book"> <class name="CompactDisc" persistence-capable-superclass="store.Product"> ... Insereix el nom de la classe

Estratègia superclass-table (especificant el discriminador) Insereix el nom que li especifiquem … <class name="Product"> <inheritance strategy="new-table"> <discriminator strategy=“value-map“ value=“PRODUCT> <column name="PRODUCT_TYPE"/> </discriminator> </inheritance> </class> <class name="Book" persistence-capable-superclass="store.Product"> <inheritance strategy="superclass-table"> <discriminator value="BOOK"/> <class name="TravelGuide" persistence-capable-superclass="store.Book"> <discriminator value="TRAVELGUIDE"/> <class name="CompactDisc" persistence-capable-superclass="store.Product"> <discriminator value="COMPACTDISC"/> ...

Fitxer de metadades de l’exemple <?xml version="1.0"?> <!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN" "http://java.sun.com/dtd/jdo_2_0.dtd"> <jdo> <package name="es2"> <class name="Persona"> <field name="grupp" persistence-modifier="persistent" /> <inheritance strategy="new-table"> <discriminator strategy="class-name"> <column name="tipus_persona"/> </discriminator> </inheritance> </class> <class name="Empleat" persistence-capable-superclass="es2.Persona"> <inheritance strategy="superclass-table"/> <class name="Grup"> <field name="persones" mapped-by="grupp"> <collection element-type="es2.Persona"/> </field> </package> </jdo>

Fitxer de propietats La connexió a la BD es fa mitjançant JDBC El nom de la BD és prova La classe PersistenceManagerFactory en la implementació de JPOX és org.jpox.PersistenceManagerFactoryImpl javax.jdo.PersistenceManagerFactoryClass= org.jpox.PersistenceManagerFactoryImpl javax.jdo.option.ConnectionDriverName=com.mysql.jdbc.Driver javax.jdo.option.ConnectionURL=jdbc:mysql://localhost/prova javax.jdo.option.ConnectionUserName=login javax.jdo.option.ConnectionPassword=password

Definició de l’esquema de la BD Si assignem el valor “true” a la propietat org.jpox.autoCreateSchema, JPOX crearà automàticament les taules a la BD, a partir del fitxer de les classes ehnanced i del fitxer de metadades, i també del fitxer de propietats (on estan les dades de connexió a la BD) També hi ha una eina per fer-ho expressament: java -cp "..." -Djavax.jdo.option.ConnectionDriverName= com.mysql.jdbc.Driver -Djavax.jdo.option.ConnectionURL= jdbc:mysql://localhost:3306/prova org.jpox.SchemaTool -create es2/package.jdo

Esquema generat (per a l’exemple) mysql> show tables; +-----------------+ | Tables_in_prova | | grup | | jpox_tables | | persona | 4 rows in set (0.00 sec)

Treballar amb un esquema existent Si ja tenim la base de dades creada amb dades, també podem mapejar-ho amb les classes mitjançant el fitxer de metadades Exemple Taula PERSONAdb: CODIdb (clau primària), NOMdb, COGNOMdb Classe persona: nom, cognom Fitxer de metadades (pàg. següent)

Treballar amb un esquema existent <?xml version="1.0"?> <!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 1.0//EN" "http://java.sun.com/dtd/jdo_1_0.dtd"> <jdo> <package name="es2"> <class name="Persona" identity-type="datastore" table="PERSONAdb"> <datastore-identity> <column name="CODIdb"/> </datastore-identity> <field name="nom"> <column name="NOMdb" length="255" jdbc-type="VARCHAR"/> </field> <field name="cognom"> <column name="COGNOMdb" length="255" </class> </package> </jdo>

Treballar amb un esquema existent D’aquesta forma, no controlem els ids de les taules (ho fa el gestor) La clau primària ha de ser sobre una única columna, i ha de ser d’un tipus que es pugui mapejar a java.lang.Long (INT, INTEGER, SMALLINT...) Quan es fan insercions, poden haver problemes de duplicació de claus amb les ja existents Si cal, també es podria configurar per tenir-hi el control (vegeu documentació)

Datastore identity i claus primàries També, des de JDO 2.0 (i JPOX 1.1) se pot assignar una certa “estratègia” a la generació d’identificadors Per exemple: <class name="Persona" identity-type="datastore"> <datastore-identity strategy="autoassign"/> ... </class> També es pot especificar quin és el atribut que es correspon amb la primary key (vegeu documentació)

Insercions package es2; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.Transaction; import java.util.Properties; public class Insercions { public static void main(String[] args) Properties props = new Properties(); props.setProperty("javax.jdo.PersistenceManagerFactoryClass", "org.jpox.PersistenceManagerFactoryImpl"); props.setProperty("javax.jdo.option.ConnectionDriverName", "com.mysql.jdbc.Driver"); props.setProperty("javax.jdo.option.ConnectionURL", "jdbc:mysql:///prova"); props.setProperty("org.jpox.autoCreateSchema","true"); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); Persona p1 = new Persona("pep", "garcia", 1970); Persona p2 = new Persona("josep", "fernandez", 1965); Empleat e1 = new Empleat("joan","sanchez",1975,1000); pm.makePersistent(p1); pm.makePersistent(p2); pm.makePersistent(e1); Grup g1 = new Grup("grup1"); g1.afegeixPersona(p1); g1.afegeixPersona(p2); g1.afegeixPersona(e1); Grup g2 = new Grup("grup2"); pm.makePersistent(g1); pm.makePersistent(g2); tx.commit(); } finally if (tx.isActive()) tx.rollback(); pm.close(); return;

Insercions des d’un JSP <%@ page language="java" import="es2.*,javax.jdo.*,java.util.Properties" %> <html> <head><title>JSP Page</title></head> <body> <% PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); Persona p1 = new Persona("pep", "garcia", 1970); Persona p2 = new Persona("josep", "fernandez", 1965); Empleat e1 = new Empleat("joan","sanchez",1975,1000); pm.makePersistent(p1); pm.makePersistent(p2); pm.makePersistent(e1); Grup g1 = new Grup("grup1"); g1.afegeixPersona(p1); g1.afegeixPersona(p2); g1.afegeixPersona(e1); Grup g2 = new Grup("grup2"); pm.makePersistent(g1); pm.makePersistent(g2); tx.commit(); } finally out.println("entre en finally"); if (tx.isActive()) tx.rollback(); pm.close(); %> Insercions des d’un JSP <%! Properties props; PersistenceManagerFactory pmf; public void jspInit() { props = new Properties(); props.setProperty("javax.jdo.PersistenceManagerFactoryClass", "org.jpox.PersistenceManagerFactoryImpl"); props.setProperty("javax.jdo.option.ConnectionDriverName", "com.mysql.jdbc.Driver"); props.setProperty("javax.jdo.option.ConnectionURL", "jdbc:mysql://localhost:3306/prova"); props.setProperty("org.jpox.autoCreateSchema","true"); pmf = JDOHelper.getPersistenceManagerFactory(props); } %>

MakePersistentAll El mètode MakePersistentAll permet fer persistents un grup d’instàncies de cop: ... Persona p1 = new Persona("pep", "garcia", 1970); Persona p2 = new Persona("josep", "fernandez", 1965); Empleat e1 = new Empleat("joan","sanchez",1975,1000); Vector v = new Vector(); v.add(p1); v.add(p2); v.add(e1); pm.makePersistentAll(v);

Consulta tx.begin(); package es2; Extent ext = pm.getExtent(Grup.class,false); Query query = pm.newQuery(ext,"nom==nomgrup"); query.declareParameters("String nomgrup"); Collection res = (Collection)query.execute("grup1"); Iterator it = res.iterator(); while (it.hasNext()) { Grup g1 = (Grup) it.next(); System.out.println(g1.getNom()); Set ps = g1.getPersones(); Iterator itp = ps.iterator(); while (itp.hasNext()) Persona p = (Persona)itp.next(); if (p instanceof Empleat) Empleat e = (Empleat) p; System.out.println(e.getNom()+ ". Salari: " + e.getSalari()); } else System.out.println(p.getNom()); query.close(res); tx.commit(); finally { if (tx.isActive()) tx.rollback(); pm.close(); return; package es2; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.Transaction; import java.util.Properties; import javax.jdo.Extent; import javax.jdo.Query; import java.util.Iterator; import java.util.Set; import java.util.Collection; public class Consulta { public static void main(String[] args) { Properties props = new Properties(); props.setProperty("javax.jdo.PersistenceManagerFactoryClass", "org.jpox.PersistenceManagerFactoryImpl"); props.setProperty("javax.jdo.option.ConnectionDriverName", "com.mysql.jdbc.Driver"); props.setProperty("javax.jdo.option.ConnectionURL", "jdbc:mysql:///prova"); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { Consulta

Sobre els Extents Un Extent identifica sobre quines instàncies s’ha de fer una consulta (filtre) Té informació sobre: La classe de les instàncies Si s’utilitzen subclasses d’ella Una col·lecció d’iteradors actius sobre l’Extent Per tant, no es fa cap acció quan es construeix un Extent, per exemple amb Extent ext = pm.getExtent(Grup.class,true); Les instàncies no es recuperen fins que se n’obté un iterador (amb totes les instàncies de la classe): Iterator it = extent.iterator(); O bé fins que s’executa una query sobre l’Extent: Query query = pm.newQuery(ext,"nom==nomgrup"); query.declareParameters("String nomgrup"); Collection res = (Collection)query.execute("grup1");

Més exemples de consultes Consulta bàsica sobre un atribut: Empleats amb salari > 20.000 Class empClasse = Empleat.class; Extent extEmpleat = pm.getExtent(empClasse, false); String filtre = “salari > 20000”; Query q=pm.newQuery(extEmpleat, filtre); Collection empleats = (Collection) q.execute ();

Més exemples de consultes Consulta amb ordenació: Empleats amb salari > 20.000 ordenats per ordre ascendent de salari Class empClasse = Empleat.class; Extent extEmpleat = pm.getExtent(empClasse, false); String filtre = “salari > 20000”; Query q=pm.newQuery(extEmpleat, filtre); q.setOrdering (“salari ascending”); Collection empleats = (Collection) q.execute ();

Més exemples de consultes Consulta parametritzada: Empleats amb salari > paràmetre (20.000) Class empClasse = Empleat.class; Extent extEmpleat = pm.getExtent(empClasse, false); String filtre = “salari > sal”; String param = “Float sal”; Query q=pm.newQuery(extEmpleat, filtre); q.declareParameters(param); Collection empleats = (Collection)q.execute(new Float(20000.0));

Més exemples de consultes Consulta sobre un atribut amb referència única Persones del grup amb nom “grup1” Class persClasse = Persona.class; Extent extPersona = pm.getExtent(persClasse,true); String filtre = “grup.nom == nomGrup”; String param = “String nomGrup”; Query q=pm.newQuery(extPersona, filtre); q.declareParameters(param); Collection persones = (Collection)q.execute(new String(“grup1”));

Més exemples de consultes Consulta sobre un atribut amb referència múltiple Grups que tenen almenys un empleat amb salari > paràmetre (20.000) Class grupClass = Grup.class; Extent extGrup = pm.getExtent (grupClass, false); String vars = “Empleat emp”; String filtre = “persones.contains(emp) && emp.salary > sal”; String param = “float sal”; Query q = pm.newQuery (extGrup, filtre); q.declareParameters (param); q.declareVariables (vars); Collection grups = (Collection) q.execute (new Float (20000.0));

JDO 2.0 (i per tant JPOX 1.1) permet definir les consultes en SQL: Consultes SQL JDO 2.0 (i per tant JPOX 1.1) permet definir les consultes en SQL: Query query = pm.newQuery( "javax.jdo.query.SQL", "SELECT * FROM Persona"); query.setResultClass(Persona.class); List results = (List) query.execute(); Persona p = (Persona) result.iterator().next(); Problema: com gestionar l’herència?

Pool de connexions Es pot fàcilment configurar el gestor de persistencia perquè utilitzi un pool de connexions a la BD Propietat org.jpox.connectionPoolingType, que per defecte té el valor és “None” Per utilitzar DBCP: properties.setProperty( "org.jpox.connectionPoolingType", "DBCP");

Modificacions Si modifiquem un atribut d’una instància, aquest serà escrit automàticament a la BD quan es faci el commit Persistència transitiva o persistència per “abast” (reachability, alcance) Quan tenim una instància persistent que té com a atribut una referència a altre objecte que encara és temporal

Persistència transitiva o persistència per “abast” Volem afegir un atribut adreca a Persona que sigui la seva adreça, i que serà una referència a una classe Adreca Si tenim una instància de Persona p que ja és persistent, quan creem una instància de Adreca a, encara és “transient” En el moment en què afegim la referència a la instància persistent amb un p.afegeixAddress(a); la instància es farà persistent en el moment en què es faci el commit, sense necessitat de fer el pm.makePersistent(a); En general, totes les referències que té una instància persistent, es faran també persistents amb el commit Noteu que és semblant al que passava amb Serialization Això ens permetrà escriure molt de codi sense fer constants crides a makePersistent

Exemple de persistència transitiva Properties props = readProperties(“jdo.properties"); pmf = JDOhelper.getPersistenceManagerFactory(props); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); tx.begin(); Persona p = new Persona(“toni”,”navarrete”,1973); Adreca a = new Address(“passeig circumval·lació 8”, “08003”, “Barcelona”, “Espanya”); p.afegeixAdreca(a); pm.makePersistent(p); /* p es marca com a persistent i també a, ja que p en conté la referència */ tx.commit();   // p i a són escrits a la BD pm.close();

Exemple de persistència transitiva Properties props = readProperties(“jdo.properties"); pmf = JDOhelper.getPersistenceManagerFactory(props); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); tx.begin(); Persona p = new Persona(“toni”,”navarrete”,1973); pm.makePersistent(p); // p es marca com a persistent tx.commit();   // p és escrit a la BD Adreca a = new Address(“passeig circumval·lació 8”, “08003”, “Barcelona”, “Espanya”); p.afegeixAdreca(a); // a es marca com a persistent tx.commit(); // a és escrit a la BD pm.close();

Eliminació d’instàncies Dos mètodes del PersistenceManager: deletePersistent(instància) deletePersistentAll(col·lecció d’instàncies) L’eliminació no és transitiva! A diferència de makePersistent, s’ha de cridar a deletePersistent per a cada instància que s’ha d’eliminar

Estats d’una instància Transient (fugaç, passatger) La instància s’ha creat però no se li ha comunicat al PersistenceManager Persistent-new Representa una instància que s’ha marcat com a persistent en la transacció actual Quan una instància transient és el paràmetre d’un makePersistent En aquest moment, el gestor li assigna un identificador JDO a la instància També es passen a persistent-new totes les instàncies “accessibles” des de la instància actual (persistència transitiva o per abast)

Estats d’una instància Persistence-clean Les dades de la instància concideixen amb les guardades al magatzem de dades (això passa quan es fa el commit de la transacció activa) Altres: Persistent-dirty Fa referència a les instàncies que han canviat les seves dades en l’actual transacció (no coincideixen amb les dades del magatzem) Hollow (buit, hueco) La instància no conté totes les dades que hi ha al magatzem (això pot passar amb les consultes, típicament quan obtenim una instància i tanquem el gestor de persistència, es perden les referències) Persistent-deleted La instància es vol borrar amb un deletePersistent, però encara no s’ha fet el commit de la transacció activa

Mètodes del cicle de vida d’una instància makePersistent makePersistentAll makeTransient makeTransientAll deletePersistent deletePersistentAll

Exemple d’estats d’instància Properties props = readProperties(“jdo.properties"); pmf = JDOhelper.getPersistenceManagerFactory(props); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); tx.begin(); Persona p = new Persona(“toni”,”navarrete”,1973); //la instància p és transient pm.makePersistent(p); //la instància p és persistent-new tx.commit();  //la instància p és persistent-clean Adreca a = new Adreca(“passeig circumval·lació 8”,  “08003”, “Barcelona”, “Espanya”); //la instància a és transient p.afegeixAdreca(a); //la instància a és persistent-new //la instància p és persistent-dirty tx.commit();  //les instàncies p i a són persistent-clean pm.close();

Accessos fora de transaccions No es poden accedir als objectes fora de les transaccions Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); ... p = (Persona)it.next(); tx.commit();    } finally { tx.rollback(); } System.out.println(p.getNom.charAt(0));

Accessos fora de transaccions Una forma simple per poder fer-ho s’ha de declarar la propietat NontransactionalRead a true: props.setProperty( "javax.jdo.option.NontransactionalRead", "true");

Atach/detach produeix una execpció NullPointerException Quan el gestor de persistència (PersistenceManager) es tanca, els objectes que s’han obtingut amb ell queden en estat de hollow i no es pot accedir als seus atributs Per exemple (encara que la propietat NontransactionalRead sigui true): Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); ... p = (Persona)it.next(); tx.commit();    } finally { tx.rollback(); pm.close(); } System.out.println(p.getNom.charAt(0)); produeix una execpció NullPointerException

Atach/detach S’ha de separar (“detach”) l’objecte del graf abans de tancar el gestor: Cal definir la classe com a detachable al fitxer de metadades: <class name="Persona" detachable="true"> Cal separar l’objecte: Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); ... Persona p2 = (Persona)it.next(); p = (Persona)pm.detachCopy(p2); tx.commit();    } finally { tx.rollback(); pm.close(); } System.out.println(p.getNom.charAt(0));

Atach/detach En el cas de col·leccions: Collection persones; PersistenceManager pm=getPersistenceManager(); Transaction tx=pm.currentTransaction(); try { tx.begin(); Query q = pm.newQuery(Persona.class); Collection query_persones=q.execute(); persones = pm.detachCopyAll(query_persones); tx.commit(); } ...

Atach/detach Si després s’hagués de tornar d’incloure al graph: Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); ... Persona p2 = (Persona)it.next(); p = (Persona)pm.detachCopy(p2); tx.commit();   // p és escrit a la BD } p.setNom("toni"); tx = pm.currentTransaction(); pm.attachCopy(p,true); tx.commit();

Atach/detach Però el “detach” no és transitiu. Això donarà error: Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); ... Persona p2 = (Persona)it.next(); p = (Persona)pm.detachCopy(p2); tx.commit();    } finally { tx.rollback(); pm.close(); } System.out.println(p.getAdreca.getNomCarrer());

Per defecte, només es recuperen els següents atributs: Fetch groups Per defecte, només es recuperen els següents atributs: primitius : boolean, byte, char, double, float, int, long, short Classes de tipus primitius: Boolean, Byte, Character, Double, Float, Integer, Long, Short java.lang.String, java.lang.Number java.math.BigDecimal, java.math.BigInteger java.util.Date

I després s’especifica que el gestor utililitzarà aquest fetch-group: Fetch groups Per modificar aquest comportament per defecte s’ha de definir un “fetch group” propi: <class name="Persona" detachable="true"> ... <field name="adreca" persistence-modifier="persistent"/> <fetch-group name="detach_persona_adreca"> <field name="adreca"/> </fetch-group> </class> I després s’especifica que el gestor utililitzarà aquest fetch-group: pm.getFetchPlan().addGroup("detach_persona_adreca");

Fetch groups Persona p; pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); try { tx.begin(); pm.getFetchPlan().addGroup("detach_persona_adreca"); ... Persona p2 = (Persona)it.next(); p = (Persona)pm.detachCopy(p2); tx.commit();    } finally { tx.rollback(); pm.close(); } System.out.println(p.getAdreca.getNomCarrer());

Adreces JDO http://java.sun.com/products/jdo http://www.jpox.org O www.jcp.org (JSR-12) http://www.jpox.org (website de JPOX) http://www.jdocentral.com (molts de recursos sobre JDO) http://www.javaworld.com/channel_content/jw-persistence-index.shtml (canal sobre persistència de JavaWorld)