En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Disseny de la persistènciaHibernate i frameworks de persistència POJO
Toni Navarrete
Enginyeria del Software II – UPF 2007
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
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
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 3
Recordatori: problemes (i aventatges) d’altres solucions
• JDBC– Permet treballar amb un Gestor de BD– Dóna accés a SQL– Usa el model relacional
• 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, referides a l’esquema de la BD
– SQL no està realment estandaritzat, amb la qual cosa la portabilitat no sempre és total
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
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– Si cal canviar l’esquema de la BD també cal
canviar les classes– 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
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 5
Recordatori: problemes (i aventatges) d’altres solucions
• EJB 2.1 i la persistència manegada pel contenidor (CMP)– Defineix un mecanisme de persistència
transparent• Els mètodes dels EJB d’entitat són independents
de l’esquema de dades• Llenguatge de consultes abstracte, independent
de SQL
– EJB és una arquitectura complexa i amb un alt overhead
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 6
Objectius dels frameworks de persistència POJO (Plain Old Java Object)• Treballar amb el model de classes i deixar al
framework de persistència la traducció al model relacional– Normalment el mapping s’especifica mitjançant un
fitxer XML
• Operacions d’accés a la BD referides a:– Guardar objectes (inserts)– Modificar objectes (updates)– Eliminar objectes (deletes)– Recuperar col·leccions d’objectes (selects)
• Independència entre el model de classes i el model físic de la BD
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
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 7
Hibernate
• Hibernate és un d’aquests frameworks de persistència POJO
• Codi obert i gratuït (llicència GNU LGPL)
• Molt estès, gran comunitat de desenvolupadors i usuaris
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 8
Problemes dels frameworks de persistència
• Adoptar un API no estandaritzada é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 del framework
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 9
JDO
• És una iniciativa de la comunitat Java per crear un framework estandaritzat per a persistència (de la mateixa forma 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)– JPOX és la implementació de referència (i lliure), però no és
prou estable• JDO pot suportar no només BD relacionals sinó
qualsevol forma d’emmagatzemantge permanent (XML, fitxers,...)
• És molt “transparent” (per exemple, persistència transitiva)
• No ha acabat de consolidar-se com a estàndard• Actualment un projecte Apache: http://db.apache.org/jdo/
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 10
Java Persistence API (JPA)
• Definida en EJB 3.0 (JavaEE 5)http://java.sun.com/javaee/technologies/persistence.jsp
• La idea original era que JPA es fes a partir de JDO, però ha acabat essent una especificació diferent– http://db.apache.org/jdo/jdo_v_jpa.html– http://db.apache.org/jdo/jdo_v_jpa_orm.html
• JPA substitueix als EJB d’entitat– Ja no cal definir les interfícies– No s’utilitza el deployment descriptor
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 11
Java Persistence API (JPA)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 12
JPA
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 13
Hibernate i els estàndards
• Hibernate no té cap relació amb JDO
• Té una API “EntityManager” per permetre compatibilitat amb Java Persistenca API
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 14
Nota: Hibernate i JDBC
• Hibernate no substitueix JDBC– Són complementaris– Hibernate utilitza 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
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 15
Exemple d’una petita aplicació amb Hibernate
• Farem una classe que permet guardar a la BD instàncies d’una classe Persona
• Una altra classe ens permetrà recuperar les instàncies de Persona a la BD
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 16
La classe Persona
package persones;public class Persona { Long id; //a Hibernate cal definir un identificador d’instància, amb els seus mètodes get i set String nom, cognom; int anyNaixement = 0; public Persona() {} // a Hibernate é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 Long getId() { return id; } private void setId(Long id) { this.id = id; } 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
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 17
Mapeig entre classe i taula(es) de la BD
• Fitxer persona.hbm.xml<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="persones">
<class name="Persona" table="PERSONA">
<id name="id" column="PERSONA_ID">
<generator class="native"/>
</id>
<property name="nom"/>
<property name="cognom"/>
<property name="anyNaixement"/>
</class>
</hibernate-mapping>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 18
• Fitxer hibernate.cfg.xml<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Propietats de la BD -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate_db1
</property>
<property name="connection.username">usuari</property>
<property name="connection.password">password</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
Configuració del gestor de BD (i altres propietats)
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 19 Configuració del gestor de BD (i altres propietats)• Fitxer hibernate.cfg.xml
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Esborra i torna a crear l’esquema de la BD a cada execució (només per proves) -->
<!-- Cal comentar-ho quan volguem fer consultes!!!-->
<property name="hbm2ddl.auto">create</property>
<!-- Referència al(s) fitxer(s) de mapping -->
<mapping resource="persones/Persona.hbm.xml"/>
</session-factory>
</hibernate-configuration>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 20 Inserció d’instànciespackage persones;
import org.hibernate.*; import org.hibernate.cfg.*;
public class Insercions {
static Session session;
static SessionFactory sessionFactory;
public static void main(String[] args) {
try {
// Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.getCurrentSession();
//comença la transacció
session.beginTransaction();
//crea les instàncies que calgui i les guarda
Persona p1 = new Persona("pep", "garcia", 1970);
Persona p2 = new Persona("josep", "fernandez", 1965);
session.save(p1);
session.save(p2);
//fa el commit de la transacció
session.getTransaction().commit();
//tanca el sessionFactory i allibera els recursos associats (caches, pools,…)
sessionFactory.close();
} catch (RuntimeException e) {
if (session!=null) session.getTransaction().rollback();
e.printStackTrace();
}
}
}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 21 Consulta d’instànciespackage persones;
import org.hibernate.*; import org.hibernate.cfg.*;
public class Consulta {
static Session session; static SessionFactory sessionFactory;
public static void main(String[] args) {
try {
// Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.getCurrentSession();
//comença la transacció
session.beginTransaction();
//recupera les instàncies de la classe Persona i escriu els seus atributs per pantalla
java.util.Iterator it = session.createQuery("from Persona").list().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());
}
//fa el commit de la transacció
session.getTransaction().commit();
// tanca el sessionFactory i allibera els recursos associats (caches, pools,…) //
sessionFactory.close();
} catch (RuntimeException e) {
if (session!=null) session.getTransaction().rollback();
e.printStackTrace();
}
}
}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 22 Modificació d’instànciespackage persones;
import org.hibernate.*; import org.hibernate.cfg.*;
public class Modificacio {
static Session session; static SessionFactory sessionFactory;
public static void main(String[] args) {
try {
// Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.getCurrentSession();
//comença la transacció
session.beginTransaction();
//recupera les instàncies de la classe Persona
java.util.Iterator it = session.createQuery("from Persona").list().iterator();
while (it.hasNext()) {
Persona p = (Persona)it.next();
if (p.getNom().equals("pep"))
p.setNom("josep");
}
//fa el commit de la transacció
session.getTransaction().commit();
// tanca el sessionFactory i allibera els recursos associats (caches, pools,…) //
sessionFactory.close();
} catch (RuntimeException e) {
if (session!=null) session.getTransaction().rollback();
e.printStackTrace();
}
}
}
NOTA: si l’objecte que modifiquem no s’ha guardat o recuperat en la mateixa transacció, cal afegir
session.update(p);
En l’exemple això no és necessari
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 23 Esborrat d’instànciespackage persones;
import org.hibernate.*; import org.hibernate.cfg.*;
public class Esborrat {
static Session session; static SessionFactory sessionFactory;
public static void main(String[] args) {
try {
// Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.getCurrentSession();
//comença la transacció
session.beginTransaction();
//recupera les instàncies de la classe Persona i escriu els seus atributs per pantalla
java.util.Iterator it = session.createQuery("from Persona").list().iterator();
while (it.hasNext()) {
Persona p = (Persona)it.next();
if (p.getAnyNaixement()<1970)
session.delete(p);
}
//fa el commit de la transacció
session.getTransaction().commit();
// tanca el sessionFactory i allibera els recursos associats (caches, pools,…) //
sessionFactory.close();
} catch (RuntimeException e) {
if (session!=null) session.getTransaction().rollback();
e.printStackTrace();
}
}
}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 24
Més sobre consultes• Les consultes s’expressen en HQL
– Sempre fent referència al model de classes, no al de la BD• Exemple: persones nascudes abans d’un cert any:
public static void imprimeixLlistatAbansAny(int any) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); java.util.Iterator it = session.createQuery( "from Persona p where p.anyNaixement < ?") .setInteger(0, any) .list().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()); } session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); }
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 25
Altres exemples de consultes
• PaginacióQuery q = session.createQuery("from Persona"); q.setFirstResult(20); q.setMaxResults(10);List persones = q.list();
• OrdenacióQuery q = session.createQuery(
"from Persona p order by p.cognom");
• AgregacionsQuery q = session.createQuery(
"select avg(p.pes), sum(p.pes), max(p.pes), count(p) from Persona p");
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 26
Recuperar objecte per ID
• L’objecte de sessió té un mètode load que permet recuperar un objecte persistent si sabem el seu identificador:
Persona p = (Persona) session.load(
Persona.class, new Long(1234) );
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 27
Estats d’una instància
• transient– La instància no està, i no ha estat mai, associada a un context de
persistència (sessió). No té un id persistent (valor de clau primària)• persistent
– La instància està associada a un context de persistència (sessió). Té un id persistent i normalment està associada a una fila en la BD. Hibernate garantitza que l’estat de la instància és equivalent a l’estat persistent, mentre segueixi associat a la transacció
• detached– La instància va estar associada amb un context de persistència
(sessió), però aquest es va tancar. Té un id persistent i normalment està associada a una fila en la BD, però els canvis en l’estat de la instància no es veuen reflectits a la BD
• Notes:– Totes les comunicacions amb la BD (lectures i escriptures) es fan dins
d’una transacció– En els nostres exemples, una sessió (un context de persistència) està
emmarcada per una transacció. Més endavant veurem que aquest patró es pot canviar
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 28
Flush d’una sessió
• Totes les instàncies amb estat “persistent” que es modifiquen dins d’una sessió es poden actualitzar a la BD directament cridant el mètode flush (sense haver de fer-ho un a un)Persona p1 = (Persona) session.load(Persona.class, new Long(1) );
Persona p2 = (Persona) session.load(Persona.class, new Long(2) );
p1.setNom(“joan”);
p2.setNom(“jordi”);
session.flush();
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 29
Millorant l’estructurapackage util;import org.hibernate.*;import org.hibernate.cfg.*;
public class HibernateUtil {
private static final SessionFactory sessionFactory; static { try { // Create the SessionFactory from hibernate.cfg.xml sessionFactory = new
Configuration().configure().buildSessionFactory(); } catch (Exception e) { e.printStackTrace(); throw new ExceptionInInitializerError(e); } }
public static SessionFactory getSessionFactory() { return sessionFactory; }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 30
package persones;import org.hibernate.*; import org.hibernate.cfg.*; import util.HibernateUtil;
public class Persona { Long id; String nom, cognom; int anyNaixement = 0; public Persona() {}
//Constructors, gets i sets i altres mètodes
public void guarda() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); session.save(this); session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); }
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 31
public void esborra() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); session.delete(this); session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); }
public void actualitza() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); session.update(this); session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); } public static java.util.List getLlistaPersones() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); java.util.List persones = session.createQuery("from Persona").list();
session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); return persones; } }
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 32
package clients;import org.hibernate.*; import org.hibernate.cfg.*; import persones.*;public class Client { public static void main(String[] args) { //crea les instàncies que calgui i les guarda Persona p1 = new Persona("pep", "garcia", 1970); Persona p2 = new Persona("josep", "fernandez", 1965); p1.guarda(); p2.guarda();
java.util.List persones = Persona.getLlistaPersones(); java.util.Iterator it = persones.iterator();
while (it.hasNext()) { Persona p = (Persona)it.next(); if (p.getNom().equals("pep")) p.esborra(); else { p.setNom(p.getNom().toUpperCase()); p.setCognom(p.getCognom().toUpperCase()); p.actualitza(); System.out.println("Nom: "+p.getNom()); System.out.println("Cognom: "+p.getCognom()); System.out.println("Any naixement: "+p.getAnyNaixement()); } } }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 33
Un exemple més complet (amb herència i associacions)
Persona
Empleat
Grup0..*0..*
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 34
Fitxers de mapping
• Un per classe o un per tot el paquet• Herència
– Cal definir entre les tres formes d’implementar l’herència
– Si és el cas, cal definir quin atribut s’utilitza com a discriminador, i quin valor pren cada subclasse
• Associacions– 1-a-1, 1-a-molts o molts-a-molts– Unidireccionals o bidireccionals– Amb o sense taula de join
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 35
<hibernate-mapping package="persones"> <class name="Persona" table="PERSONA"> <id name="id" column="PERSONA_ID"> <generator class="native"/> </id> <discriminator column="TIPUS" type="string"/> <property name="nom"/> <property name="cognom"/> <property name="anyNaixement"/>
<subclass name="Empleat" extends="Persona" discriminator-value="persones.Empleat">
<property name="salari"/> </subclass> </class> <class name="Grup" table="GRUP"> <id name="id" column="GRUP_ID"> <generator class="native"/> </id> <property name="nom"/>
<set name="persones" table="GRUP_PERSONA"> <key column="GRUP_ID"/> <many-to-many column="PERSONA_ID" class="Persona"/> </set> </class></hibernate-mapping>
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 36
package persones;import java.util.*; import org.hibernate.*; import org.hibernate.cfg.*;public class Insercions { public static void main(String[] args) { try { // Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.getCurrentSession(); //comença la transacció session.beginTransaction(); //crea les instàncies que calgui i les guarda Persona toni = new Persona("toni","navarrete",1973); session.save(toni); Persona dani = new Persona("dani","soto",1973); session.save(dani); Empleat pep = new Empleat("pep","garcia",1977,30000); session.save(pep); Grup g = new Grup("grupo 1"); Set s = new HashSet(); s.add(toni); s.add(pep); g.setPersones(s); session.save(g); //fa el commit de la transacció session.getTransaction().commit(); sessionFactory.close(); } catch (Exception e) { e.printStackTrace(); } }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 37
package persones;import java.util.*; import org.hibernate.*; import org.hibernate.cfg.*;public class Consultes { public static void main(String[] args) { try { // Crea la Session de hibernate a partir del fitxer hibernate.cfg.xml SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.getCurrentSession(); //comença la transacció session.beginTransaction(); //recupera les instàncies de la classe Grup java.util.List grups = session.createQuery("from Grup").list(); System.out.println("Nombre de grups: "+grups.size()); for (int i=0;i<grups.size();i++) { Grup g = (Grup)grups.get(i); System.out.println(" Nom: "+g.getNom()); System.out.println(" Número de membres: "+g.getPersones().size()); java.util.Iterator it = g.getPersones().iterator(); while (it.hasNext()) { Persona p = (Persona)it.next(); System.out.println(" Nom: "+p.getNom()+" "+p.getCognom()); if (p instanceof Empleat) System.out.println(" Salari: "+((Empleat)p).getSalari()); } } //fa el commit de la transacció session.getTransaction().commit(); sessionFactory.close(); } catch (Exception e) { e.printStackTrace(); }}
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 38
Consultes amb joins
• Un empleat pertany a 1 departament, un departament té molts empleats– Empleat té un atribut departament– Departament té un atribut col·lecció empleats
• Empleats d’un departament:– “from Empleat e where
e.departament.nom=‘Informàtica’ ”– “select e
from Empleat e join e.departament d
where d.nom=‘Informàtica’ ”
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 39
Aspectes a tenir en compte sobre les referències i col·leccions
• Persistència transitiva– Quan guardem una instància, cal també guardar
expressament cada una de les instàncies referenciades per ella (no com amb serialització o JDO)
– Per evitar això: es pot configurar al fitxer de mapping:• <one-to-many name="persones" cascade="persist"/>• <one-to-many name="persones"
cascade="persist,delete,lock"/>
– Quan recuperem una instància, podem recuperar les seves referències a altres instàncies sense haver de definir una altra consulta
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 40
Aspectes a tenir en compte sobre les referències i col·leccions
• Lazy associations– Quan recuperem una instànica (grup), la
col·lecció d’instàncies referenciades (conjunt de persones) no es carrega en memòria fins que no s’hi accedeix
– Aquest comportament per defecte es pot modificar: diverses formes de fetching i caches
• Instàncies detached– Quan recuperem una instància dins d’una
transacció, un cop es tanca la transacció, no podem accedir a les seves referències
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 41
Arquitectura
En
gin
yeri
a d
el S
W II
: Dis
sen
y d
e la
pe
rsis
tèn
cia
. H
iber
na
te i
fra
me
wo
rks
de
per
sist
ènc
ia P
OJO
Pàgina 42
Sessions i transaccions
• El patró més habitual és el de session-per-request (no necessàriament session-per-operation)
• Converses més llargues– No és viable mantenir oberta una sessió
entre diferents peticions o per una aplicació– session-per-request-with-detached-objects– session-per-conversation (la sessió es pot
desconnectar de la capa de JDBC després d’un commit, i tornar a connectar quan rep una altra petició del mateix client)
Top Related