enginyeria del sw ii: disseny de la persistència. jdo disseny de la persistència jdo i frameworks...
TRANSCRIPT
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
O
Disseny de la persistènciaJDO i frameworks de persistència
Toni Navarrete
Enginyeria del Software II – UPF 2006
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 2
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 3
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 4
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 5
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 de frameworks ORM existents:– Hibernate– 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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 6
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 7
JDO• És una 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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 8
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 9
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 10
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 SGBD
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 11
JDO
JDOcentral.com: A comparion between Java Data Objects (JDO), Serialization and JDBC for Java Persistance
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 12
Exemple d’una petita aplicació JDO amb la JDORI
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 13 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) { 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; }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 14
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 15
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 16
• 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
Jars necessaris
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 17
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 18
Enhancement
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 19
Enhancement
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 20
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 21
Fent una aplicació
• Ara farem una aplicació que crea instàncies de Persona i les guarda a una BD
• Per a la BD utilitzarem un petit gestor que JDORI porta com a referència i que es diu FOStore (File Object Store)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 22
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 23
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)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 24
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 25
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 26
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 27
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); } }}
Creació d’una BD en FOStore• Aquest codi crea un
magatzem al directori database
• Propietat com.sun.jdori.option.ConnectionCreate a true
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 28
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() { try{ 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ó
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 29
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);
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 30
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() { try{ 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); }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 31
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 */
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 32
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); }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 33
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() {}}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 34
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 35
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); }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 36
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 pràcticament es
considera 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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 37
Un exemple més complet (amb JPOX)
Persona
Empleat
Grup0..10..*
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 38 Personapackage 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; } }
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 39 Gruppackage 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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 40
Empleatpackage 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; } }
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 41 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></class>
</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)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 42
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"/>
</field>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 43
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> <field name="secondName" persistence-modifier="persistent"> <column length=“50" jdbc-type="VARCHAR"/>
</field> <field name="user" persistence-modifier="persistent"> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 44
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"> </field> </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> <field name="user" persistence-modifier="persistent"> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 45 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"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="addresses" persistence-modifier="persistent"> <collection element-type=" mydomain.Address"/> </field> </class>
<class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> <field name="street" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 46
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"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="addresses" persistence-modifier="persistent" mapped-by="account"> <collection element-type=“mydomain.Address"/> </field> </class>
<class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> <field name="street" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> <field name="account" persistence-modifier="persistent"> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 47
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"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="addresses" persistence-modifier="persistent"> <collection element-type=" mydomain.Address"/> <join/> </field> </class>
<class name="Address" identity-type="datastore"> <field name="city" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> <field name="street" persistence-modifier="persistent"> <column length="50" jdbc-type="VARCHAR"/> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 48
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> <field name="suppliers" persistence-modifier="persistent"> <collection element-type="mydomain.Supplier"> <collection/> </field> </class>
<class name="Supplier" identity-type="datastore"> <field name="name" persistence-modifier="persistent"> <column length=“100" jdbc-type="VARCHAR"/> </field> <field name="products" persistence-modifier="persistent"> <collection element-type="mydomain.Product"> <collection/> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 49 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> <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> </field> </class>
<class name="Supplier" identity-type="datastore"> <field name="name" persistence-modifier="persistent"> <column length="100" jdbc-type="VARCHAR"/> </field> <field name="products" persistence-modifier="persistent" mapped-by="suppliers"> <collection element-type="mydomain.Product"/> </field> </class></package>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 50
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:
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 51 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">
<inheritance strategy="new-table"/>
</class>
<class name="Book" persistence-capable-superclass="store.Product">
<inheritance strategy="new-table"/>
</class>
<class name="TravelGuide" persistence-capable-superclass="store.Book">
<inheritance strategy="new-table"/>
</class>
<class name="CompactDisc" persistence-capable-superclass="store.Product">
<inheritance strategy="new-table"/>
</class>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 52 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.
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 53 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>
<class name="TravelGuide" persistence-capable-superclass="store.Book">
<inheritance strategy="superclass-table"/>
</class>
<class name="CompactDisc" persistence-capable-superclass="store.Product">
<inheritance strategy="superclass-table"/>
</class>
...
Insereix el nom de la classe
NOTA: En algunes versions és necessari especificar un valor per defecte per als atributs específics de la subclasse, almenys si aquesta és un número
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 54 Estratègia superclass-table (especificant
el discriminador)…<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"/> </inheritance></class><class name="TravelGuide" persistence-capable-superclass="store.Book"> <inheritance strategy="superclass-table"> <discriminator value="TRAVELGUIDE"/> </inheritance></class> <class name="CompactDisc" persistence-capable-superclass="store.Product"> <inheritance strategy="superclass-table"> <discriminator value="COMPACTDISC"/> </inheritance></class> ...
Insereix el nom que li especifiquem
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 55
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"/>
<field name="salari"> <column name="salari" jdbc-type="INTEGER" default-value="0"/>
</field> </class>
<class name="Grup"> <field name="persones" mapped-by="grupp"> <collection element-type="es2.Persona"/> </field>
</class> </package></jdo>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 56
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=usuari
javax.jdo.option.ConnectionPassword=password
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 57
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/provaorg.jpox.SchemaTool -create es2/package.jdo
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 58
Esquema generat (per a l’exemple)
mysql> show tables;
+-----------------+
| Tables_in_prova |
+-----------------+
| grup |
| persona |
+-----------------+
2 rows in set (0.00 sec)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 59
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)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 60
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" jdbc-type="VARCHAR"/>
</field> </class>
</package></jdo>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 61
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ó)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 62
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ó)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 63 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("javax.jdo.option.ConnectionUserName","usuari");
props.setProperty("javax.jdo.option.ConnectionPassword","password");
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; }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 64
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(); }
%>
<%! 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:///prova");
props.setProperty("javax.jdo.option.ConnectionUserName","usuari");
props.setProperty("javax.jdo.option.ConnectionPassword","password");
props.setProperty("org.jpox.autoCreateSchema","true");
pmf = JDOHelper.getPersistenceManagerFactory(props); }
%>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 65
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);
...
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 66 Consulta
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"); props.setProperty("javax.jdo.option.ConnectionUserName",
"usuari"); props.setProperty("javax.jdo.option.ConnectionPassword",
"password"); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); try {
tx.begin(); 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; }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 67
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");
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 68
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 ();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 69
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 ();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 70
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));
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 71
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”));
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 72
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));
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 73
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?
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 74
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");
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 75
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 76
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 77
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();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 78
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
tx.begin();
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();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 79
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 80
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 d’aquests instància (persistència transitiva o per abast)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 81
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 82
Mètodes del cicle de vida d’una instància
• makePersistent
• makePersistentAll
• makeTransient
• makeTransientAll
• deletePersistent
• deletePersistentAll
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 83 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-cleantx.begin();
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-cleanpm.close();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 84
Accessos fora de transaccions
• No es poden accedir als objectes fora de les transaccionsPersona 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));
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 85
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");
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 86 Atach/detach
• 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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 87 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));
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 88
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();
}
...
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 89 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(); try {
tx.begin(); pm.attachCopy(p,true); tx.commit();
}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 90 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());
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 91
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 92
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");
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 93
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());
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. JD
OPàgina 94
Adreces JDO
• http://java.sun.com/products/jdoO 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)