Disseny de la persist ncia jdo i frameworks de persist ncia
This presentation is the property of its rightful owner.
Sponsored Links
1 / 75

Disseny de la persistència JDO i frameworks de persistència PowerPoint PPT Presentation


  • 66 Views
  • Uploaded on
  • Presentation posted in: General

Disseny de la persistència JDO i frameworks de persistència. Toni Navarrete Enginyeria del Software II – UPF 200 4. Recordatori: problemes (i aventatges) d’altres solucions. Serialitzatió Avantantges: Estàndard en qualsevol ambient Java Fàcil d’utilitzar

Download Presentation

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

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Disseny de la persist ncia jdo i frameworks de persist ncia

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

Toni Navarrete

Enginyeria del Software II – UPF 2004


Recordatori problemes i aventatges d altres solucions

Recordatori: problemes (i aventatges) d’altres solucions

  • Serialitzatió

    • Avantantges:

      • Estàndard en qualsevol ambient Java

      • Fàcil d’utilitzar

      • El model de dades és directament el de les classes (aprofita OO)

    • Inconvenients:

      • No té les característiques d’un gestor de BD robust

        • Per exemple, índexs, transaccions,...

      • No és escalable


Recordatori problemes i aventatges d altres solucions1

Recordatori: problemes (i aventatges) d’altres solucions

  • JDBC

    • Dóna accés a SQL

    • Usa el model relacional de SQL

      • No el model orientat a objectes de Java

      • Procedimental en lloc d’OO

      • El processament de dades es fa mitjançant SQL i no Java

    • Les operacions són expressades en relació a taules, files i columnes

    • SQL no està realment estandaritzat, amb la qual cosa la portabilitat no sempre és real


Recordatori problemes i aventatges d altres solucions2

Recordatori: problemes (i aventatges) d’altres solucions

  • Quan s’utilitza JDBC, el programador està obligat a treballar amb dos models de dades diferents, així com amb dos paradigmes i llenguatges d’accés a les dades distints.

    • El resultat sol ser que s’escriu codi Java procedural per manipular les taules. No OO


Conseq ncia

Conseqüència

  • Moltes organitzacions comencen a desenvolupar el seu propi framework per a persistència i O/R mapping, que permeti els seus objectes interactuar amb la BD de forma transparent

  • Exemples

    • Castor

    • Apache ObJectRelationalBridge (OJB)

    • ODMG 3.0, desenvolupat pelObject Data Management Group (ODMG). Inicalment en C++ i Smaltalk, ha estat una de les bases de JDO i n’és un subconjunt


Problemes i avantatges d altres solucions

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


Disseny de la persist ncia jdo i frameworks de persist ncia

JDO

  • És una nova iniciativa de la comunitat Java per crear un framework estandaritzat per a persistència (de la mateixa que Swing ho és per a interfície gràfica)

  • JDO és només una especificació, de la qual els fabricants de software faran implementacions (a vegades lliures, a vegades no)

  • Normalment parlarem de JDO per accedir a BDR, però pot ser qualsevol forma d’emmagatzemantge permanent (XML, fitxers,...)

  • Sun produeix el JDORI (JDO Reference Implementation) com a una implementació per demostrar que l’especificació és vàlida. Però no està pensada per explotació en entorns reals


Disseny de la persist ncia jdo i frameworks de persist ncia

JDO

  • JDO: capacitats de BD de JDBC amb la integració Java de la serialització

  • JDO usa el model d’objectes Java

  • Les instàncies tenen un identificador únic (OID únic)

  • Soporta transaccions

  • Emmagatzemar instàncies, recuperar-les i modificar-es és transparent

  • Resum: mínima intrusió i màxima transparència


Comparaci jdo amb les altres alternatives

Comparació JDO amb les altres alternatives

  • EJB també defineix un mecanisme de persistència transparent (Container Managed Persistence, CMP), però EJB és una arquitectura complexa i amb més overhead que JDO

  • Serialització també és OO però no és apte per treballar amb grans volums de dades, no és escalable, i no té suport per índexs, transaccions i demés mecanismes d’un SGBD


Jdo i jdbc

JDO i JDBC

  • JDO no substituirà JDBC

    • Són complementàries

    • Les implementacions de JDO solen utilitzar JDBC per sota per connectar-se a la BD

      • JDBC és útil per gestionar connexions amb la BD

      • JDBC és força sòlid

      • JDBC està soportat per la majoria de fabricants de SGBC


Disseny de la persist ncia jdo i frameworks de persist ncia

JDO

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


Exemple d una petita aplicaci jdo amb la jdori

Exemple d’una petita aplicació JDO amb la JDORI


Exemple d una classe persistent amb jdo

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;

}

}


Declaraci de classes persistents

Declaració de classes persistents

  • L’únic requeriment és que la classe ha de tenir un constructor sense arguments

  • Ara podem crear instàncies d’aquesta classe Person i guardar-las a la BDR

  • JDO utilitza un fitxer de metadades per dir quines classes seran persistents i reflectir tota la informació relacionada amb la persistència (ho veurem amb més detall més endavant)

    • Fitxer amb extensió .jdo


Exemple de fitxer de metadades es2 jdo

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">

  • Restricció:

    • El nom del fitxer és el del paquet (al directori arrel) o també es pot fer separat per classes (Persona.jdo en el nostre cas) i van dins del directori es2


Jars necessaris

Jars necessaris

  • JDO es pot baixar de www.jcp.org (JSR-12)

  • Per treballar amb la implementació de referència:

    • jdo.jar

      • Les interfícies estàndard i les classes definides a l’especificació JDO

    • jdori.jar

      • La implementació de referència de Sun

    • btree.jar

      • Implementa un petit gestor d’emmagatzament per la JDORI de Sun

    • jta.tar

      • Java Transaction API que usa JDO per definir transaccions

    • antlr.jar

      • Serveix per parsejar el llenguatges de consultes de JDO

    • xerces.jar

      • Per parsejar XML


Enhancement

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


Enhancement1

Enhancement


Enhancement2

Enhancement


Enhancement3

Enhancement

  • java com.sun.jdori.enhancer.Main es2.jdo es2/Persona.class

  • Algunes opcions:

    • -v (verbose)

    • -d (a un directori distint, sense sobreescriure el .class original):

  • java com.sun.jdori.enhancer.Main -v -d enhanced es2.jdo es2/Persona.class

  • Cada fabricant d’implementacions JDO té el seu enhancer que es crida de forma diferent

  • Noteu que l’enhancement és independent del magatzem de dades que utilitzem després


Fent una aplicaci

Fent una aplicació

  • Ara farem una aplicació que crea instàncies de Persona i les guarda a una BD

  • JDORI porta un petit gestor com a referència que es diu FOStore (File Object Store)


Estructura de classes de jdo

Estructura de classes de JDO

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


Estructura de classes de jdo1

Estructura de classes de JDO

  • Per obtenir i configurar un PersistenceManager es fa mitjançant la interfície PersistenceManagerFactory

  • A la vegada, el PersistenceManagerFactory s’obté a partir d’un mètode estàtic de la classe JDOHelper, segons unes propietats (url de connexió, login, password i el nom de la implementació de JDO que utilitzem)


Estructura de classes de jdo2

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ípciament jdo.properties) o ser configurades des de programa


Estructura de classes de jdo3

Estructura de classes de JDO

  • Un PersistenceManager té associat una instància de la interfície JDO Transaction, per a controlar el començament i finalització d’una transacció

  • Per obtenir la instància de Transaction ho fem amb el mètode currentTransaction de la instància de PersistenceManager

  • En JDO tota acció que hagi de modificar la BD estarà emmarcada dins d’una transacció

    • Usarem els mètodes begin, commit i rollback de la instància de Transaction


Fostore

FOStore

  • JDORI porta un petit gestor com a referència que es diu FOStore (File Object Store)

  • Anem a crear una BD per guardar les futures instàncies de la classe Persones

  • jdo.properties

  • Directori database

  • CreateDatabase.java


Creaci d una bd en fostore

package es2;

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.Properties;

import javax.jdo.JDOHelper;

import javax.jdo.PersistenceManagerFactory;

import javax.jdo.PersistenceManager;

import javax.jdo.Transaction;

public class CreateDatabase{

public static void main(String[] args){

create();

}

public static void create(){

try{

InputStream propertyStream = new FileInputStream("es2/jdo.properties");

Properties jdoproperties = new Properties();

jdoproperties.load(propertyStream);

jdoproperties.put("com.sun.jdori.option.ConnectionCreate","true");

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties);

PersistenceManager pm = pmf.getPersistenceManager();

Transaction tx = pm.currentTransaction();

tx.begin();

tx.commit();

} catch (Exception e) {

System.err.println("Exception creating db");

e.printStackTrace();

System.exit(-1);

}

}

}

Creació d’una BD en FOStore

  • Aquest codi crea un magatzem al directori database

  • Propietat com.sun.jdori.option.ConnectionCreate a true


Creant l aplicaci

Creant l’aplicació

package es2;

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.Properties;

import java.util.Map;

import java.util.HashMap;

import javax.jdo.JDOHelper;

import javax.jdo.PersistenceManagerFactory;

import javax.jdo.PersistenceManager;

import javax.jdo.Transaction;

public class Aplicacio1{

protected PersistenceManagerFactory pmf;

protected PersistenceManager pm;

protected Transaction tx;

public Aplicacio1() {

try{

InputStream propertyStream = new FileInputStream("es2/jdo.properties");

Properties jdoproperties = new Properties();

jdoproperties.load(propertyStream);

pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties);

pm = pmf.getPersistenceManager();

tx = pm.currentTransaction();

} catch (Exception e) {

System.err.println("Exception creating db");

e.printStackTrace();

System.exit(-1);

}

}

public void executeTransaction() {

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();

}

}


Sobre les propietats

Sobre les propietats

  • També es poden especificar les propietats dins del codi:

    ...

    Properties props = new Properties();

    props.setProperty("javax.jdo.PersistenceManagerFactoryClass",

    "com.sun.jdori.fostore.FOStorePMF ");

    props.setProperty("javax.jdo.option.ConnectionURL",

    "fostore:database/fostoredb");

    props.setProperty("javax.jdo.option.ConnectionUserName",“toni");

    props.setProperty("javax.jdo.option.ConnectionPassword",“toni");

    props.setProperty("javax.jdo.option.Optimistic",“false");

    pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties);


Creant l aplicaci amb una millor organitzaci

Creant l’aplicació amb una millor organització

package es2;

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.Properties;

import javax.jdo.JDOHelper;

import javax.jdo.PersistenceManagerFactory;

import javax.jdo.PersistenceManager;

import javax.jdo.Transaction;

public abstract class Aplicacio{

protected PersistenceManagerFactory pmf;

protected PersistenceManager pm;

protected Transaction tx;

public abstract void execute();

public Aplicacio() {

try{

InputStream propertyStream = new FileInputStream("es2/jdo.properties");

Properties jdoproperties = new Properties();

jdoproperties.load(propertyStream);

pmf = JDOHelper.getPersistenceManagerFactory(jdoproperties);

pm = pmf.getPersistenceManager();

tx = pm.currentTransaction();

} catch (Exception e) {

System.err.println("Exception creating db");

e.printStackTrace();

System.exit(-1);

}

}

public void executeTransaction() {

try{

tx.begin();

execute();

tx.commit();

} catch (Throwable exception){

exception.printStackTrace(System.err);

if (tx.isActive())

tx.rollback();

}

}

}

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);

}

}


Consultes

Consultes

  • Extent és una interfície que permet accedir a totes les instàncies d’una classe persistent

  • Mètode getExtent del PersistenceManager

    Extent extent = pm.getExtent(Persona.class,false);

    /* el segon paràmetre indica si també considerar

    les instàncies de les subclasses */


Consulta de totes les persones emmagatzemades

Consulta de totes les persones emmagatzemades

package es2;

import java.util.Iterator;

import javax.jdo.Extent;

public class LlistatPersones extends Aplicacio{

public static void main(String[] args) {

LlistatPersones lp = new LlistatPersones();

lp.executeTransaction();

}

public void execute() {

Extent extent = pm.getExtent(Persona.class,false);

Iterator it = extent.iterator();

while (it.hasNext()) {

Persona p = (Persona)it.next();

System.out.println("Nom: " + p.getNom());

System.out.println("Cognom: " + p.getCognom());

System.out.println("Any naixement: " + p.getAnyNaixement());

System.out.println();

}

extent.close(it);

}

}


Consulta de totes les persones emmagatzemades sense transacci

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()

{}

}


Consultes i filtres

Consultes i filtres

  • La interfície Query permet definir filtres sobre un Extent, per fer consultes més específiques (i no de tots els elements)

  • Quan es crea una Query s’especifica l’Extent i la condició:

    Query q =

    pm.newQuery(extent,"nom == nomPersona");

    q.declareParameters("String nomPersona");

  • També es pot crear la Query directament sobre la classe:

    Query q = pm.newQuery(Persona.class,"nom==\"toni\"");

  • En especificar la condició podem utilitzar els operadors comparatius, aritmètics,... de Java


Consulta del cognom d una persona concreta

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 == nomPersona");

q.declareParameters("String nomPersona");

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);

}

}


M s coses

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)

  • Associacions entre classes (relacions entre taules) i herència

    • Generació automàtica de l’esquema de la BD

    • Capacitat per configurar el mapping objecte/relacional a l’hora de crear les taules

  • Permet:

    • Insercions, eliminacions i modificacions d’objectes

    • Consultes

  • Persistència transitiva


Un exemple m s complet amb jpox

Un exemple més complet (amb JPOX)

Grup

Persona

0..*

0..1

Empleat


Persona

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;

}

}


Disseny de la persist ncia jdo i frameworks de persist ncia

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


Empleat

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;

}

}


Fitxer de metadades package jdo

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


Extensions als elements de metadades

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>


Tractament de les relacions relacions 1 a 1

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">

    <extension vendor-name="jpox" key="length" value="max 20"/>

    </field>

    </class>

    <class name="Account" identity-type="datastore">

    <field name="firstName" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="secondName" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="user" persistence-modifier="persistent">

    </field>

    </class>

    </package>


Tractament de les relacions relacions 1 a 11

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">

    <extension vendor-name="jpox" key="length" value="max 20"/>

    </field>

    <field name="account" persistence-modifier="persistent">

    </field>

    </class>

    <class name="Account" identity-type="datastore">

    <field name="firstName" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="secondName" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="user" persistence-modifier="persistent">

    </field>

    </class>

    </package>


Tractament de les relacions relacions 1 a n

Tractament de les relacions. Relacions 1 a N

  • Normal (amb Set):

    <package name="mydomain">

    <class name="Address" identity-type="datastore">

    <field name="city" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="street" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    </class>

    <class name="Account" identity-type="datastore">

    <field name="firstname" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="lastname" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="addresses" persistence-modifier="persistent">

    <collection element-type="mydomain.Address"/>

    </field>

    </class>

    </package>


Tractament de les relacions relacions 1 a n1

Tractament de les relacions. Relacions 1 a N

  • Inverse-bidirectional (amb Set):

    <package name="mydomain">

    <class name="Address" identity-type="datastore">

    <field name="city" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="street" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="account" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="collection-field" value="addresses"/>

    </field>

    </class>

    <class name="Account" identity-type="datastore">

    <field name="firstname" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="lastname" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="addresses" persistence-modifier="persistent">

    <collection element-type="mydomain.Address">

    <extension vendor-name="jpox" key="owner-field" value="account"/>

    <collection/>

    </field>

    </class>

    </package>


Tractament de les relacions relacions m a n

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">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </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">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="products" persistence-modifier="persistent">

    <collection element-type="mydomain.Product">

    <collection/>

    </field>

    </class>

    </package>


Tractament de les relacions relacions m a n1

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">

    <extension vendor-name="jpox" key="length" value="max 50"/>

    </field>

    <field name="price" persistence-modifier="persistent">

    </field>

    <field name="suppliers" persistence-modifier="persistent">

    <collection element-type="mydomain.Supplier">

    <extension vendor-name="jpox" key="table-name" value="PRODUCTS_SUPPLIERS"/>

    <extension vendor-name="jpox" key="owner-column-name" value="PRODUCT_ID"/>

    <extension vendor-name="jpox" key="element-column-name" value="SUPPLIER_ID"/>

    <collection/>

    </field>

    </class>

    <class name="Supplier" identity-type="datastore">

    <field name="name" persistence-modifier="persistent">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="products" persistence-modifier="persistent">

    <collection element-type="mydomain.Product">

    <extension vendor-name="jpox" key="table-name" value="PRODUCTS_SUPPLIERS"/>

    <extension vendor-name="jpox" key="owner-column-name" value="SUPPLIER_ID"/>

    <extension vendor-name="jpox" key="element-column-name" value="PRODUCT_ID"/>

    <collection/>

    </field>

    </class>

    </package>


Tractament de l her ncia

Tractament de l’herència

  • Utilitza una taula per a cada classe de l’arbre d’herència, on cada taula contindrà només els atributs propis de la classe (no duplicació d’atributs a diferents classes)

    • Recordatori: solució 3 del tema “Disseny de la persistència. Introducció i mapping objecte/relacional”

  • S’espera que en futures versions sigui configurable. Altres implementacions de JDO ho permeten


Tractament de l her ncia1

Tractament de l’herència

  • Exemple:

    <package name="org.jpox.sample.store">

    <class name="Product">

    <field name="name">

    <extension vendor-name="jpox" key="length" value="max 100"/>

    </field>

    <field name="description">

    <extension vendor-name="jpox" key="length" value="max 255"/>

    </field>

    <field name="price"/>

    </class>

    <class name="Book" persistence-capable-superclass="org.jpox.samples.store.Product">

    <field name="isbn">

    <extension vendor-name="jpox" key="length" value="max 20"/>

    </field>

    <field name="author">

    <extension vendor-name="jpox" key="length" value="max 40"/>

    </field>

    <field name="title">

    <extension vendor-name="jpox" key="length" value="max 40"/>

    </field>

    </class>

    <class name="TravelGuide" persistence-capable-superclass="org.jpox.samples.store.Book">

    <field name="country">

    <extension vendor-name="jpox" key="length" value="max 40"/>

    </field>

    </class>

    <class name="CompactDisc" persistence-capable-superclass="org.jpox.samples.store.Product">

    <field name="artist">

    <extension vendor-name="jpox" key="length" value="max 40"/>

    </field>

    <field name="title">

    <extension vendor-name="jpox" key="length" value="max 40"/>

    </field>

    </class>

    </package>


Fitxer de propietats

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 lido és org.jpox.PersistenceManagerFactoryImpl

    javax.jdo.PersistenceManagerFactoryClass=

    org.jpox.PersistenceManagerFactoryImpl

    javax.jdo.option.ConnectionDriverName=

    com.mysql.jdbc.Driver

    javax.jdo.option.ConnectionURL=

    jdbc:mysql:///prova


Definici de l esquema de la bd

Definició de l’esquema de la BD

  • Si assignem el valor “true” a la propietat org.jpox.autoCreateSchema, JPOX crearà automàticament les taules a la BD, a partir del fitxer de les classes ehnanced i del fitxer de metadades, i també del fitxer de propietats (on estan les dades de connexió a la BD)

  • També hi ha una eina per fer-ho expressament:

    java -cp "..."

    -Djavax.jdo.option.ConnectionDriverName=com.mysql.jdbc.Driver

    -Djavax.jdo.option.ConnectionURL=

    jdbc:mysql://localhost:3306/prova

    org.jpox.SchemaTool -create es2/package.jdo


Esquema generat

Esquema generat

mysql> show tables;

+-----------------+

| Tables_in_prova |

+-----------------+

| empleat |

| grup |

| jpox_tables |

| persona |

| sequence_table |

+-----------------+

5 rows in set (0.07 sec)


Treballar amb un esquema existent

Treballar amb un esquema existent

  • Si ja tenim la base de dades creada amb dades, també podem mapejar-ho amb les classes mitjançant el fitxer de metadades

  • Exemple

    • Taula PERSONAdb: CODIdb (clau primària), NOMdb, COGNOMdb

    • Classe persona: nom, cognom

    • Fitxer de metadades (pàg. següent)


Treballar amb un esquema existent1

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>


Treballar amb un esquema existent2

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ó)


Insercions

try

{

tx.begin();

Persona p1 = new Persona("pep", "garcia", 1970);

Persona p2 = new Persona("josep", "fernandez", 1965);

Empleat e1 = new Empleat("joan","sanchez",1975,1000);

pm.makePersistent(p1);

pm.makePersistent(p2);

pm.makePersistent(e1);

Grup g1 = new Grup("grup1");

g1.afegeixPersona(p1);

g1.afegeixPersona(p2);

g1.afegeixPersona(e1);

Grup g2 = new Grup("grup2");

pm.makePersistent(g1);

pm.makePersistent(g2);

tx.commit();

}

finally

{

if (tx.isActive()) tx.rollback();

pm.close();

}

return;

}

}

Insercions

package es2;

import javax.jdo.JDOHelper;

import javax.jdo.PersistenceManager;

import javax.jdo.PersistenceManagerFactory;

import javax.jdo.Transaction;

import java.util.Properties;

public class Insercions

{

public static void main(String[] args)

{

Properties props = new Properties();

props.setProperty("javax.jdo.PersistenceManagerFactoryClass", "org.jpox.PersistenceManagerFactoryImpl");

props.setProperty("javax.jdo.option.ConnectionDriverName","com.mysql.jdbc.Driver");

props.setProperty("javax.jdo.option.ConnectionURL",

"jdbc:mysql:///prova");

props.setProperty("org.jpox.autoCreateSchema","true");

PersistenceManagerFactory pmf =

JDOHelper.getPersistenceManagerFactory(props);

PersistenceManager pm = pmf.getPersistenceManager();

Transaction tx = pm.currentTransaction();


Insercions des d un jsp

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://localhost:3306/prova");

props.setProperty("org.jpox.autoCreateSchema","true");

pmf = JDOHelper.getPersistenceManagerFactory(props);

}

%>


Makepersistentall

MakePersistentAll

  • El mètode MakePersistentAll permet fer persistents un grup d’instàncies de cop:

    ...

    Persona p1 = new Persona("pep", "garcia", 1970);

    Persona p2 = new Persona("josep", "fernandez", 1965);

    Empleat e1 = new Empleat("joan","sanchez",1975,1000);

    Vector v = new Vector();

    v.add(p1);

    v.add(p2);

    v.add(e1);

    pm.makePersistentAll(v);

    ...


Consulta

tx.begin();

Extent ext = pm.getExtent(Grup.class,true);

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;

}

}

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");

PersistenceManagerFactory pmf =

JDOHelper.getPersistenceManagerFactory(props);

PersistenceManager pm = pmf.getPersistenceManager();

Transaction tx = pm.currentTransaction();

try {


Sobre els extents

Sobre els Extents

  • Un Extent identifica sobre quines instàncies s’ha de fer una consulta (filtre)

  • Té informació sobre:

    • La classe de les instàncies

    • Si s’utilitzen subclasses d’ella

    • Una col·lecció d’iteradors actius sobre l’Extent

  • Per tant, no es fa cap acció quan es construeix un Extent, per exemple amb

    Extent ext = pm.getExtent(Grup.class,true);

  • Les instàncies no es recuperen fins que se n’obté un iterador (amb totes les instàncies de la classe):

    Iterator it = extent.iterator();

  • O bé fins que s’executa una query sobre l’Extent:

    Query query = pm.newQuery(ext,"nom==nomgrup");

    query.declareParameters("String nomgrup");

    Collection res = (Collection)query.execute("grup1");


M s exemples de consultes

Més exemples de consultes

  • Consulta bàsica sobre un atribut:

    • Empleats amb salari > 20.000

      Class empClasse = Empleat.class;

      Extent extEmpleat = pm.getExtent(empClasse, false);

      String filtre = “salari > 20000”;

      Query q=pm.newQuery(extEmpleat, filtre);

      Collection empleats = (Collection) q.execute ();


M s exemples de consultes1

Més exemples de consultes

  • Consulta amb ordenació:

    • Empleats amb salari > 20.000 ordenats per ordre ascendent de salari

      Class empClasse = Empleat.class;

      Extent extEmpleat = pm.getExtent(empClasse, false);

      String filtre = “salari > 20000”;

      Query q=pm.newQuery(extEmpleat, filtre);

      q.setOrdering (“salari ascending”);

      Collection empleats = (Collection) q.execute ();


M s exemples de consultes2

Més exemples de consultes

  • Consulta parametritzada:

    • Empleats amb salari > paràmetre (20.000)

      Class empClasse = Empleat.class;

      Extent extEmpleat = pm.getExtent(empClasse, false);

      String filtre = “salari > sal”;

      String param = “Float sal”;

      Query q=pm.newQuery(extEmpleat, filtre);

      q.declareParameters(param);

      Collection empleats =

      (Collection)q.execute(new Float(20000.0));


M s exemples de consultes3

Més exemples de consultes

  • Consulta sobre un atribut amb referència única

    • Persones del grup amb nom “grup1”

      Class persClasse = Persona.class;

      Extent extPersona = pm.getExtent(persClasse,true);

      String filtre = “grup.nom == nomGrup”;

      String param = “String nomGrup”;

      Query q=pm.newQuery(extPersona, filtre);

      q.declareParameters(param);

      Collection persones =

      (Collection)q.execute(new String(“grup1”));


M s exemples de consultes4

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));


Modificacions

Modificacions

  • Si modifiquem un atribut d’una instància, aquest serà escrit automàticament a la BD quan es faci el commit

  • Persistència transitiva o persistència per “abast” (reachability, alcance)

    • Quan tenim una instància persistent que té com a atribut una referència a altre objecte que encara és temporal


Persist ncia transitiva o persist ncia per abast

Persistència transitiva o persistència per “abast”

  • Volem afegir un atribut adreca a Persona que sigui la seva adreça, i que serà una referència a una classe Adreca

  • Si tenim una instància de Persona p que ja és persistent, quan creem una instància de Adreca a, encara és “transient”

  • En el moment en què afegim la referència a la instància persistent amb un p.afegeixAddress(a); la instància es farà persistent en el moment en què es faci el commit, sense necessitat de fer el pm.makePersistent(a);

  • En general, totes les referències que té una instància persistent, es faran també persistents amb el commit

    • Noteu que és semblant al que passava amb Serialization

  • Això ens permetrà escriure molt de codi sense fer constants crides a makePersistent


Exemple de persist ncia transitiva

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();


Eliminaci d inst ncies

Eliminació d’instàncies

  • Dos mètodes del PersistenceManager:

    • deletePersistent(instància)

    • deletePersistentAll(col·lecció d’instàncies)

  • L’eliminació no és transitiva!

    • A diferència de makePersistent, s’ha de cridar a deletePersistent per a cada instància que s’ha d’eliminar


Estats d una inst ncia

Estats d’una instància

  • Transient (fugaç, passatger)

    • La instància s’ha creat però no se li ha comunicat al PersistenceManager

  • Persistent-new

    • Representa una instància que s’ha marcat com a persistent en la transacció actual

      • Quan una instància transient és el paràmetre d’un makePersistent

      • En aquest moment, el gestor li assigna un identificador JDO a la instància

      • També es passen a persistent-new totes les instàncies “accessibles” des de la instància actual (persistència transitiva o per abast)


Estats d una inst ncia1

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)

    • Persistent-deleted

      • La instància es vol borrar amb un deletePersistent, però encara no s’ha fet el commit de la transacció activa


M todes del cicle de vida d una inst ncia

Mètodes del cicle de vida d’una instància

  • makePersistent

  • makePersistentAll

  • makeTransient

  • makeTransientAll

  • deletePersistent

  • deletePersistentAll


Exemple d estats d inst ncia

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 Address(“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();


Adreces jdo

Adreces JDO

  • http://java.sun.com/products/jdo

    • O www.jcp.org (JSR-12)

  • 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)

  • http://www.jpox.org

    • (website de JPOX)


  • Login