Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porRosa Romero Godoy Modificado hace 10 años
1
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 II – UPF 2006
2
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
3
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
4
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
5
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
6
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
7
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
8
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
9
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
10
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
11
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 11 JDO JDOcentral.com: A comparion between Java Data Objects (JDO), Serialization and JDBC for Java Persistance
12
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 12 Exemple d’una petita aplicació JDO amb la JDORI
13
Enginyeria del SW II: Disseny de la persistència. JDO Pà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; }
14
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
15
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 15 Exemple de fitxer de metadades (es2.jdo) o Nota: algunes implementacions fixen com s’ha d’anomenar el fitxer de metadades
16
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 16 JDO es pot baixar de www.jcp.org (JSR-12)www.jcp.org 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
17
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
18
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 18 Enhancement
19
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 19 Enhancement
20
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
21
Enginyeria del SW II: Disseny de la persistència. JDO Pà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)
22
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
23
Enginyeria del SW II: Disseny de la persistència. JDO Pà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)
24
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
25
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
26
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
27
Enginyeria del SW II: Disseny de la persistència. JDO Pà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.Conne ctionCreate a true
28
Enginyeria del SW II: Disseny de la persistència. JDO Pà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ó
29
Enginyeria del SW II: Disseny de la persistència. JDO Pà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);
30
Enginyeria del SW II: Disseny de la persistència. JDO Pà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); }
31
Enginyeria del SW II: Disseny de la persistència. JDO Pà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 */
32
Enginyeria del SW II: Disseny de la persistència. JDO Pà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); }
33
Enginyeria del SW II: Disseny de la persistència. JDO Pà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() {} }
34
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
35
Enginyeria del SW II: Disseny de la persistència. JDO Pà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); }
36
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
37
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 37 Un exemple més complet (amb JPOX) Persona Empleat Grup 0..10..*
38
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 38 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; }
39
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 39 Grup 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
40
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 40 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; }
41
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 41 Fitxer de metadades (package.jdo) <field name="grupp" persistence-modifier="persistent" /> <class name="Empleat" persistence-capable-superclass="es2.Persona"/> 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)
42
Enginyeria del SW II: Disseny de la persistència. JDO Pà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: JDO 2.0 ja integra moltes d’aquestes extensions de forma estàndard. Per exemple
43
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 43 Tractament de les relacions. Relacions 1 a 1 Single-ended
44
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 44 Tractament de les relacions. Relacions 1 a 1 Double-ended
45
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 45 Tractament de les relacions. Relacions 1 a N Unidireccional amb foreign key:
46
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 46 Tractament de les relacions. Relacions 1 a N Bidireccional amb foreign key:
47
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
48
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 48 Tractament de les relacions. Relacions M a N Amb dues taules de join (amb Set):
49
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 49 Tractament de les relacions. Relacions M a N Amb només una taula de join (amb Set):
50
Enginyeria del SW II: Disseny de la persistència. JDO Pà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:
51
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 51 Estratègia new-table (per defecte)
52
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 52 Estratègia subclass-table … … 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.
53
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 53 Estratègia superclass-table …... 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
54
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 54 Estratègia superclass-table (especificant el discriminador) …... Insereix el nom que li especifiquem
55
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 55 Fitxer de metadades de l’exemple <field name="grupp" persistence-modifier="persistent" /> <class name="Empleat" persistence-capable-superclass="es2.Persona"> <column name="salari" jdbc-type="INTEGER" default-value="0"/>
56
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
57
Enginyeria del SW II: Disseny de la persistència. JDO Pà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/prova org.jpox.SchemaTool -create es2/package.jdo
58
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 58 Esquema generat (per a l’exemple) mysql> show tables; +-----------------+ | Tables_in_prova | +-----------------+ | grup | | persona | +-----------------+ 2 rows in set (0.00 sec)
59
Enginyeria del SW II: Disseny de la persistència. JDO Pà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)
60
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 60 Treballar amb un esquema existent <column name="NOMdb" length="255" jdbc-type="VARCHAR"/> <column name="COGNOMdb" length="255" jdbc-type="VARCHAR"/>
61
Enginyeria del SW II: Disseny de la persistència. JDO Pà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ó)
62
Enginyeria del SW II: Disseny de la persistència. JDO Pà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:... També es pot especificar quin és el atribut que es correspon amb la primary key (vegeu documentació)
63
Enginyeria del SW II: Disseny de la persistència. JDO Pà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; }
64
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 64 Insercions des d’un JSP JSP Page <% 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); } %>
65
Enginyeria del SW II: Disseny de la persistència. JDO Pà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);...
66
Enginyeria del SW II: Disseny de la persistència. JDO Pà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; }
67
Enginyeria del SW II: Disseny de la persistència. JDO Pà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");
68
Enginyeria del SW II: Disseny de la persistència. JDO Pà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 ();
69
Enginyeria del SW II: Disseny de la persistència. JDO Pà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 ();
70
Enginyeria del SW II: Disseny de la persistència. JDO Pà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));
71
Enginyeria del SW II: Disseny de la persistència. JDO Pà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”));
72
Enginyeria del SW II: Disseny de la persistència. JDO Pà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));
73
Enginyeria del SW II: Disseny de la persistència. JDO Pà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?
74
Enginyeria del SW II: Disseny de la persistència. JDO Pà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");
75
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
76
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
77
Enginyeria del SW II: Disseny de la persistència. JDO Pà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();
78
Enginyeria del SW II: Disseny de la persistència. JDO Pà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();
79
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
80
Enginyeria del SW II: Disseny de la persistència. JDO Pà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)
81
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
82
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 82 Mètodes del cicle de vida d’una instància makePersistent makePersistentAll makeTransient makeTransientAll deletePersistent deletePersistentAll
83
Enginyeria del SW II: Disseny de la persistència. JDO Pà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-clean tx.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-clean pm.close();
84
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 84 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));
85
Enginyeria del SW II: Disseny de la persistència. JDO Pà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");
86
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
87
Enginyeria del SW II: Disseny de la persistència. JDO Pà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: –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));
88
Enginyeria del SW II: Disseny de la persistència. JDO Pà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(); }...
89
Enginyeria del SW II: Disseny de la persistència. JDO Pà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(); }
90
Enginyeria del SW II: Disseny de la persistència. JDO Pà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());
91
Enginyeria del SW II: Disseny de la persistència. JDO Pà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
92
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 92 Fetch groups Per modificar aquest comportament per defecte s’ha de definir un “fetch group” propi:... I després s’especifica que el gestor utililitzarà aquest fetch-group: pm.getFetchPlan().addGroup("detach_persona_adreca");
93
Enginyeria del SW II: Disseny de la persistència. JDO Pà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());
94
Enginyeria del SW II: Disseny de la persistència. JDO Pàgina 94 Adreces JDO http://java.sun.com/products/jdo O www.jcp.org (JSR-12) www.jcp.org http://www.jpox.org (website de JPOX) http://www.jdocentral.com (molts de recursos sobre JDO) http://www.javaworld.com/channel_conte nt/jw-persistence-index.shtmlhttp://www.javaworld.com/channel_conte nt/jw-persistence-index.shtml (canal sobre persistència de JavaWorld)
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.