Sei sulla pagina 1di 124

Introduzione a Hibernate

Versione preliminare Antonella Poggi Dipartimento di informatica e Sistemistica Sapienza Universit` di Roma a Progetto di Applicazioni Software Anno accademico 2008-2009

Progetto di Applicazioni Software

Anno accademico 2008-2009

Riferimenti bibliograci
Libro Java Persistence with Hibernate, Christian Bauer and Gavin King - Editore: Manning Hibernate Reference Documentation (cf. link sulla pagina web del corso)

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Argomenti principali
Introduzione ad Hibernate e suoi principali utilizzi Le basi della gestione della persistenza con Hibernate Mapping pi` complessi u Le transazioni e il ciclo di vita degli oggetti Creare un livello generico per la gestione della persistenza

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Introduzione ad Hibernate e suoi principali utilizzi

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Hibernate core
Anche noto come Hibernate o Hibernate 3.3.x Software open source e free, distribuito sotto licenza GNU ORM libreria per Java: servizio di base per la gestione della persistenza in applicazioni Java fornisce un framework per mappare un modello di dominio object-oriented su di una base di dati relazionale database caratteristica primaria: mapping da classi Java a tabelle di una base di dati (e mapping da tipi di dati Java a tipi di dati SQL) + abilit` di interrogare la basi di dati a
A. Poggi 4

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il codice dellapplicazione usa le API di Hibernate per gestire la persistenza I mapping tra classi Java e tabelle relazionali sono specicati in appositi le XML in linea di principio, lo sviluppatore ` esonerato da: e
richieste di esecuzione di chiamate SQL gestione manuale dei risultati di chiamate SQL e loro eventuale conversione in oggetti

Lapplicazione rimane portabile in tutti i sistemi di gestione supportati, con pochissimo overhead Pu` essere usato in maniera independente dal tipo di o applicazione, di piattaforma e di ambiente runtime, con tutti i JDK

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Hibernate tools
Insieme di strumenti per Hibernate 3 Forniscono dei task Ant e dei plugin Eclipse per fare reverse engineering, generazione di codice, e, pi` in u generale, per interagire con Hibernate
Ant: strumento per fare il build, la compilazione e il deployment di applicazioni Java complesse Eclipse: ambiente di sviluppo open-source, molto essibile

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate


Top down Bottom up Meet in the middle

A. Poggi

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Top Down


Si parte da un diagramma delle classi di dominio e dalla sua implementazione in Java e si ha completa libert` a rispetto allo schema della base di dati Si specicano i le XML con i mapping ed eventualmente, si pu` usare Hibernate (in particolare lo o strumento Hibernate hbm2ddl) per generare lo schema della base di dati
vantaggi: comodo quando non vi ` alcun database e preesistente svantaggi: diventa laborioso se si vogliono sfruttare tutte le caratteristiche del DBMS, e.g. stored procedure, trigger
A. Poggi 8

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Bottom up


Si parte da un base di dati esistente legacy e si ha completa libert` rispetto al dominio dellapplicazione a Si usa una serie di strumenti Hibernate per generare lo schema della base il codice Java per la gestione della persistenza, ovvero il codice delle classi persistenti
jdbcconfiguration: strumento che si connette via JDBC alla base di dati ed accede ai metadati dal catalogo della base di dati hbm2hbmxml: strumento che prende in ingresso i metadati ottenuti dal catalogo e genera i le XML dei mapping hbm2cfgxml: strumento che prende in ingresso i
A. Poggi 9

Progetto di Applicazioni Software

Anno accademico 2008-2009

metadati ottenuti dal catalogo e genera il le di congurazione di Hibernate (cf. slides pi` avanti) u

Problemi:
lo schema della base di dati deriva, nella migliore delle ipotesi, da un degrado dello schema ER non si potr` mai ottenere un diagramma delle a classi che sfrutti caratteristiche importanti della programmazione ad oggetti, e.g. ereditariet`, a polimorsmo la logica dellapplicazione ` inuenzata dalla e rappresentazione dei dati il diagramma delle classi di dominio conterr` solamente le classi persistenti a

A. Poggi

10

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Meet in the middle


Scenario pi` interessante e comune - quello del u progetto richiesto per questo corso! Si parte da un diagramma delle classi di dominio dellapplicazione e da una base di dati preesistente Non ` in generale possibile mappare un insieme di classi e di dominio su di una base di dati arbitrari si deve seguire un approccio generico allORM e ricorrere ad Hibernate quando possibile, ed in caso contrario, allapproccio generico DAO
N.B. Nella trattazione che faremo, assumeremo di usare Hibernate seguendo lapproccio Meet in the middle.
A. Poggi 11

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le basi della gestione della persistenza con Hibernate

A. Poggi

12

Progetto di Applicazioni Software

Anno accademico 2008-2009

Hibernate in azione

5 principali ingredienti di unapplicazione che fa uso di Hibernate per la gestione della persistenza

le classi di dominio realizzate in Java una base di dati, e.g. realizzata in Mysql un le che denisce il mapping di ogni classe persistente uno o pi` le di congurazione di Hibernate u le interfacce Hibernate per laccesso alla base di dati: Session, Transaction e Query - package org.hibernate

A. Poggi

13

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le classi di dominio
Le classi di dominio sono denite come in qualsiasi applicazione Java tipicamente, metodi set e get per laccesso in scrittura e lettura delle propriet` degli oggetti della a classe metodi di business della classe

A. Poggi

14

Progetto di Applicazioni Software

Anno accademico 2008-2009

Diagramma delle classi di dominio - Esempio

vincente

0..1 0..* relativa

Offerta
ammontare : int dataCreazione: Date

0..* fattaDa

Item
nome : String codice : int descrizione : String prezzoIniziale: int giornoInizio: Date giornoFine: Date calcolaTempoResiduo(): int

User
nome : String cognome : String username: String password: String email: String calcolaCostoSpedi zione(): int

Indirizzo
risiede
via : String civico : int cap: String citt: String

0..*

compratoDa

A. Poggi

15

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le classi di dominio - Esempio


package bid; import java.util.StringTokenizer; public class User { private private private private private private String nome; String cognome; String username; String password; String email; Indirizzo indirizzo;

public User(){} public User(String user){ username=user;

A. Poggi

16

Progetto di Applicazioni Software


}

Anno accademico 2008-2009

public String getNome() { return nome;} public void setNome(String nome) { this.nome=nome;} public String getCognome() { return cognome;} public void setCognome(String cognome) { this.cognome=cognome;} public String getUsername() { return username;} public void setUsername(String username) { this.username=username;} public String getPassword() { return password;} public void setPassword(String password) { this.password=password;} public String getEmail() { return email;} public void setEmail(String email) { this.email=email;}

public Indirizzo getIndirizzo() { return indirizzo;} public void setIndirizzo(Indirizzo indirizzo) { this.indirizzo=indirizzo public int calcolaCostoSpedizione {

A. Poggi

17

Progetto di Applicazioni Software

Anno accademico 2008-2009

// funzione che restituisce il costo della spedizione } }

A. Poggi

18

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di unapplicazione che usa Hibernate(1)

WORKDIR + lib <Hibernate ed altre librerie> + src +bid User.java + bin

A. Poggi

19

Progetto di Applicazioni Software

Anno accademico 2008-2009

La base di dati
` E costituita da un insieme di: tabelle vincoli store procedure, trigger ` E mantenuta allinterno di un certo DBMS, e.g. Mysql, provvisto del proprio driver jdbc

Pu` essere acceduta da un certo utente (con relativi o privilegi)

A. Poggi

20

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tabelle della base di dati - Esempio


CREATE TABLE utente ( username VARCHAR(10) PRIMARY KEY, nome VARCHAR(15), cognome VARCHAR(15), cod_fis VARCHAR(16) UNIQUE, password VARCHAR(8), email VARCHAR(20), via VARCHAR(20), civico INT, cap VARCHAR(5), citta VARCHAR(15));

A. Poggi

21

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping per le classi persistenti


File XML che denisce come si mappano le propriet` a delle classi Java persistenti sulle tabelle della base di dati Deve soddisfare la grammatica specicata allinterno di un apposito DTD, chiamato hibernate-mapping-3.0.dtd N.B. Per vericare la correttezza sintattica del le XML, Hibernate cercher` il DTD allinterno del a classpath e lo trover` nella libreria .jar di Hibernate a (ammesso che il classpath la includa) - qualora non dovesse trovare il DTD, Hibernate lo cercher` a allindirizzo specicato nella dichiarazione del DOCTYPE
A. Poggi 22

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping - Esempio


File User.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> <class name="User" table="UTENTE"> <id name="username" column="username"></id> <property name="nome" column="NOME"></property> <property name="cognome" column="COGNOME"></property> <property name="email"></property> <property name="password"></property> </class> </hibernate-mapping>

A. Poggi

23

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping - Commenti


Lelemento class dichiara il nome della classe persistente e la tabella a cui essa corrisponde dice ad Hibernate come rendere persistente e caricare gli oggetti della classe User sfruttando la tabella UTENTE, ovvero ogni istanza ` rappresentata da e una tupla della tabella Lelemento id dichiara:
il nome della propriet` della classe che gioca il ruolo a di identicatore Importante:

una classe persistente ` sempre caratterizzata da e una propriet` che ne identica le istanze a una volta creato un oggetto della classe, tale
A. Poggi 24

Progetto di Applicazioni Software

Anno accademico 2008-2009

propriet` non potr` essere modicata a a dallapplicazione (il corrispondente metodo set pu` essere denito privato) o il nome dellattributo della tabella che identica le tuple mappate su oggetti

Lelemento property dichiara il nome delle propriet` a persistenti della classe e a quali attributi della tabella corrispondono; di default, nessuna propriet` ` a e persistente Importante: come per la propriet` che identica gli a oggetti, il nome della propriet` indica ad Hibernate a quali metodi set e get usare

A. Poggi

25

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di unapplicazione che usa Hibernate(2)

WORKDIR + lib <Hibernate ed altre librerie> + src + bid User.java User.hbm.xml + bin

A. Poggi

26

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di congurazione per Hibernate


Hibernate costituisce la parte dellapplicazione che gestisce la persistenza, ovvero che si connette alla base di dati ha bisogno di avere le informazioni necessarie ad eettuare la connessione, quali il DBMS, il driver JDBC, la base di dati, utente/password, etc. Un le XML fornisce tutte queste informazioni Tale le deve soddisfare la grammatica specicata in nel DTD hibernate- configuration-3.0.dtd

A. Poggi

27

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di congurazione per Hibernate Esempio


File 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> <!-- Database connection settings --> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url"> jdbc:mysql://localhost/bid</property> <property name="connection.username">root</property> <property name="connection.password"></property> <!-- SQL dialect -->

A. Poggi

28

Progetto di Applicazioni Software

Anno accademico 2008-2009

<property name="dialect"> org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- JDBC connection pool (use C3P0) --> <property name="c3p0.min_size">5</property> <property name="c3p0.max_size">20</property> <property name="c3p0.timeout">300</property> <property name="c3p0.max_statement">50</property> <!-- Show and print nice SQL on stdout --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- List of XML mapping files --> <mapping resource="bid/User.hbm.xml" /> </session-factory> </hibernate-configuration>

A. Poggi

29

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di congurazione per Hibernate Commenti


Lelemento session-factory denisce le impostazioni per laccesso ad una particolare base di dati Le propriet` il cui nome ha la forma a (hibernate).connection.* contengono le informazioni necessarie per impostare la connessione JDBC La propriet` dialect specica la variante di SQL che a deve generare Hibernate Le propriet` c3p0.* indicano le impostazioni necessarie a a congurare il software c3p0 per il pooling di connessioni
A. Poggi 30

Progetto di Applicazioni Software

Anno accademico 2008-2009

min size: numero minimo di connessioni che deono essere pronte in ogni momento max size: numero massimo di connessioni aperte gestite dal pool timeout: tempo al termine del quale una connessione aperta non pi` usata viene rimossa u max statements: numero di prepared statements che sono mentenuti in cache

A. Poggi

31

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di unapplicazione che usa Hibernate(3)

WORKDIR + lib <Hibernate ed altre librerie> + src + bid User.java User.hbm.xml hibernate.cfg.xml + bin

A. Poggi

32

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le interfacce Hibernate
Hibernate fornisce tre principali interfacce per laccesso alla base di dati, tutte appartenenti al package org.hibernate

Session: ogni istanza rappresenta una sessione di comunicazione tra applicazione e base di dati comprende i metodi per salvare/caricare oggetti nella/dalla base di dati Transaction: ogni istanza rappresenta una transazione maggiore disaccoppiamento dellapplicazione: non ` e necessario usare lAPI JDBC per impostare una transazione gioca al ruolo di gestore di transazioni in un sistema che accede a pi` basi di dati allinterno di ununica u unit` di lavoro di sistema a
A. Poggi 33

Progetto di Applicazioni Software

Anno accademico 2008-2009

Query: interfaccia che permette di creare ed eseguire query


sia nel linguaggio di query di Hibernate (HQL) che in SQL che usino al loro interno delle variabili speciali

utile in tutti quei casi in cui era necessario ricorre ad un DCS nellapproccio DAO

A. Poggi

34

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfacce Hibernate - Esempio duso


File Bid.java
package bid; import java.util.*; import org.hibernate.*; import persistence.HibernateUtil; public class Bid { public static void main(String[] args) { //First unit of work Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); User user = new User("pippo"); String userId = (String) session.save(user); tx.commit(); session.close();

A. Poggi

35

Progetto di Applicazioni Software

Anno accademico 2008-2009

//Second unit of work session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction(); user = (User) session.get(User.class,userId); user.setNome("Filippo"); tx.commit(); session.close();

//Third unit of work session = HibernateUtil.getSessionFactory().openSession(); tx = session.beginTransaction() List users = session.createSQLQuery("select * from utente order by username").addEntity(User.class).list(); System.out.println(users.size()+" user(s) found: "); for (Iterator iter= users.iterator(); iter.hasNext(); ) { User userId = (User) iter.next(); System.out.println (userId.getNome()); } tx.commit();

A. Poggi

36

Progetto di Applicazioni Software

Anno accademico 2008-2009

session.close(); //Shutting down the application HibernateUtil.shutdown(); } }

A. Poggi

37

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfacce Hibernate - Commenti


Lutilizzo dellinterfaccia Transaction imposta lautocommit a false necessit` di chiamare il metodo a commit Tutti i comandi SQL sono generati a runtime (o eventualmente allavvio dellapplicazione per tutti quei comandi riusabili) La prima unit` di lavoro, quando eseguita, corrisponde a ad eettuare sulla base di dati un comando SQL simile a
insert into UTENTE(USERNAME,NOME,COGNOME,COD_FIS, PASSWORD,EMAIL,VIA,CIVICO,CAP,CITTA) values (pippo, null, null, null,
A. Poggi 38

Progetto di Applicazioni Software

Anno accademico 2008-2009

null, null, null, null, null, null);

La seconda unit` di lavoro mostra labilit` di Hibernate a a di:


caricare un oggetto dalla base di dati, a partire dalla classe di cui ` istanza e dal suo identicatore e il metodo get(Class,Serializable) restituisce unistanza della classe persistente data in input caratterizzata dallidenticatore in input, e null se la suddetta istanza non esiste N.B. Richiede sia denito il costruttore senza argomenti per la classe persistente eettuare un dirty checking automatico: senza che sia richiesto esplicitamente di fare lupdate dellistanza, Hibernate si accorge delle modiche apportate sulla propriet` nome ed aggiorna a
A. Poggi 39

Progetto di Applicazioni Software

Anno accademico 2008-2009

automaticamente la base di dati

La terza unit` di lavoro mostra come ` possibile a e incapsulare una query di accesso alla base di dati e ricavare dai risultati oggetti del dominio questo tipo di accesso deve essere limitato a quei casi in cui si usano i DCS nellapproccio DAO, ovvero, essenzialmente, ai casi in cui ` necessario eettuare una e ricerca sulla base di dati non di tipo diretto, e.g. FindByCriteria

A. Poggi

40

Progetto di Applicazioni Software

Anno accademico 2008-2009

Inizializzazione di Hibernate - SessionFactory


Per inizializzare Hibernate, si costruisce un oggetto SessionFactory a partire da un oggetto Configuration un oggetto Configuration, sostanzialmente, rappresenta il le di congurazione di Hibernate
SessionFactory sessionFactory = new Configuration(). configure().buildSessionFactory();
quando new Configuration() ` chiamato, e Hibernate cerca un le chiamato hibernate.properties (cf. esercitazione) e tutte le impostazioni l` denite sono associate alloggetto di Configuration
A. Poggi 41

Progetto di Applicazioni Software

Anno accademico 2008-2009

quando configure() ` chiamato, Hibernate cerca il e le hibernate.cfg.xml la locazione in cui Hibernate cerca i le suddetti ` e quella specicata nel classpath se si vuole usare unaltra locazione la si deve specicare in input esistono altre maniere di impostare delle propriet` a della connessione (cf. documentazione)

nella maggior parte delle applicazioni, SessionFactory deve essere istanziato una sola volta durante la fase di inizializzazione di Hibernate, e gioca il ruolo di gestore delle sessioni, nel senso che ogni istanza di Session deve essere creata a partire da lui ` buona prassi realizzare una classe HibernateUtil e per linizializzazione di Hibernate e la gestione della singola istanza di SessionFactory
A. Poggi 42

Progetto di Applicazioni Software

Anno accademico 2008-2009

Gestore delle sessioni - HibernateUtil


File HibernateUtil.java
package persistence; import org.hibernate.*; import org.hibernate.cfg.*; public class HibernateUtil { private static SessionFactory sessionFactory = initHibernateUtil(); private static SessionFactory initHibernateUtil(){ try { return new Configuration().configure().buildSessionFactory(); } catch (HibernateException ex) { throw new ExceptionInInitializerError(ex); } }

A. Poggi

43

Progetto di Applicazioni Software

Anno accademico 2008-2009

public static SessionFactory getSessionFactory() { return sessionFactory; } public static void shutdown() { //Close caches and connection pools getSessionFactory().close(); } }

A. Poggi

44

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di unapplicazione che usa Hibernate(4)

WORKDIR + lib <Hibernate ed altre librerie> + src +bid User.java User.hbm.xml Bid.java + persistence HibernateUtil.java hibernate.cfg.xml + bin
A. Poggi 45

Progetto di Applicazioni Software

Anno accademico 2008-2009

I mapping

A. Poggi

46

Progetto di Applicazioni Software

Anno accademico 2008-2009

In poche parole...

I le di mapping permettono di denire:

come le classi Java che realizzano classi di dominio UML persistenti siano mappate sugli elementi della base di dati informazioni sugli elementi stessi della base di dati che vengono mappati queste sono utili nellapproccio top-down, ovvero quando a partire dalle classi di dominio e dai mapping si intende generare la base di dati sottostante - in questo corso non approfondiremo questo argomento

A. Poggi

47

Progetto di Applicazioni Software

Anno accademico 2008-2009

Note importanti
1. In questa trattazione, assumeremo che la porzione persistente del diagramma delle classi e lo schema ER siano simili, nel senso che:

la realizzazione di una classe di dominio persistente ` mappata su una ed ununica tabella e le realizzazioni di due classi di dominio persistenti in ISA sono mappate su due tabelle legate da una foreign key le realizzazioni di due classi di dominio persistenti legate da unassociazione sono mappate su due tabelle legate da una o pi` catene di vincoli di u foreign key/inclusione (che eventualmente coinvolgono ulteriori tabelle)
A. Poggi 48

Progetto di Applicazioni Software

Anno accademico 2008-2009

Per tutti i casi di mapping che non rientrano tra i tipi di cui sopra, Hibernate fornisce delle soluzioni non soddisfacibili ` pertanto necessario ricorrere allapproccio DAO e

A. Poggi

49

Progetto di Applicazioni Software

Anno accademico 2008-2009

2. la realizzazione in java del diagramma delle classi di dominio segue le regole viste nel corso di Progettazione del Software, con le seguenti principali eccezioni, riguardanti i campi privati persistenti che sono collezioni:

si denisce il metodo set come per gli altri tipi di campi - ma attenzione: lo si denisce private permette ad Hibernate, ma non al client, di usarlo il metodo get non restituisce un clone della collezione, bens` la collezione stessa (restrizione di Hibernate)

A. Poggi

50

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare una classe Java signica...


stabilire una corrispondenza tra le sue istanze e le tuple di una tabella della base di dati mappare il suo identicatore mappare le sue propriet` persistenti a
propriet` che sono valori (eventualmente insiemi di a attributi/valori, ovvero con molteplicit` massima a diversa da 1) propriet` che sono istanze di unaltra classe di a dominio Java (eventualmente insiemi di istanze, ovvero con molteplicit` massima diversa da 1) a

A. Poggi

51

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare gli identicatori delle classi di dominio

La propriet` che identica una classe ` una propriet` a e a speciale

non pu` essere modicata una volta che ` stata o e assegnata ad unistanza dal punto di vista sintattico, una propriet` che a identica una classe deve essere mappata attraverso lelemento XML <id> (che DEVE essere denito)

A. Poggi

52

Progetto di Applicazioni Software

Anno accademico 2008-2009

<id> pu` avere un elemento glio <generator> che o DEVE un attributo class che specica una classe Java che implementa linterfaccia org.hibernate.id.IdentifierGenerator e che viene usata per generare identicatori unici; se tale classe prende dei parametri in ingresso, vengono specicati per mezzo di elementi gli param; Hibernate viene fornito con delle classi built-in per generare identicatori, tra le altre:

assigned signica che lapplicazione assegna lidenticatore allistanza prima che sia chiamato il metodo save - questo ` il comportamento di default se e generator non compare native: usa i generatori di identicatori forniti dal DBMS sottostante - mantiene il mapping portabile

A. Poggi

53

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare propriet` che sono valori con a molteplicit` massima pari a 1 a


Abbiamo gi` visto come si denisce nel le di mapping a come mappare una propriet` di una classe che ` un valore a e Si usa lelemento XML property Ora diciamo qualcosa in pi` sul sistema di tipi di u Hibernate....

A. Poggi

54

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il sistema di tipi di Hibernate


I tipi di Hibernate sono di fatto dei convertitori che traducono da tipi Java a tipi SQL e viceversa La maggior parte dei tipi built-in di Hibernate hanno lo stesso nome del tipo Java che mappano Possono per` esserci pi` tipi Hibernate per uno stesso o u tipo Java bisogna allora indicare nel mapping il tipo di mapping di Hibernate da usare I tipi built-in di Hibernate non possono essere usati per fare conversioni di qualsiasi tipo (e.g. da (SQL) VARCHAR a (Java) Integer), ma si possono denire dei tipi appositi per eettuare conversioni ad-hoc
A. Poggi 55

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipi primitivi di Hibernate: corrispondenze SQL-Java


Tipo Hibernate
integer long integer float double big_decimal character string byte boolean

Tipo SQL standard


INTEGER BIGINT SMALLINT FLOAT DOUBLE NUMERIC CHAR(1) VARCHAR (..) TINYINT BIT

Tipo Java
int or java.lang.Integer long or java.lang.Long short or java.lang.Integer float or java.lang.Float double or java.lang.Double java.math.BigDecimal java.lang.String java.lang.String float or java.lang.Float boolean or java.lang.Boolean

A. Poggi

56

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipi di dati Hibernate sulle date e il tempo


Tipo Hibernate
date time timestamp

Tipo SQL standard


DATE TIME TIMESTAMP

Tipo Java
java.util.Date or java.sql.Date java.util.Time or java.sql.Time java.util.Timestamp

or java.sql.Timestamp
calendar calendar_date TIMESTAMP DATE java.util.Calendar java.util.Calendar

A. Poggi

57

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come usare i tipi di Hibernate nei mapping (Esempio)


<class name="Item" table="ITEM"> (...) <property name="giornoInizio" type="time" column="INIZIO"/> </class>
N.B. Se non specichiamo il tipo di Hibernate, allora Hibernate usa la reection, ovvero risale al tipo Java della propriet` giornoInizio della classe Item e assume un a comportamento di default se abbiamo denito la propriet` giornoInizio come di a tipo java.util.Date, Hibernate cerca di convertirla nel tipo TIMESTAMP (= TIME)
A. Poggi 58

Progetto di Applicazioni Software

Anno accademico 2008-2009

Classi che realizzano tipi UML


A valle della fase di progetto, sono spesso individuati dei tipi UML che sono realizzati tramite classi Java, da importare o denite nellapplicazione stesse Le istanze di una classe che realizza un tipo UML:
sono propriet` di classi di dominio a non possono essere condivise non sono identicate da nessuna propriet` a

Per le classi che realizzano un nuovo tipo UML, ` e necessario ridenire i metodi toString, equals(), hashCode() e, se qualche funzione della classe Java eettua side-eect, clone()
A. Poggi 59

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mapping di propriet` istanze di una classe a che realizza un tipo UML

Ipotesi: come sempre, le colonne da mappare appartengono alla stessa tabella su cui ` mappata la classe e A seconda che sia o no necessario eettuare una conversione od una forma di type checking tra i valori delle propriet` della classe che realizza il tipo UML, ed il valore a degli attributi della base di dati mappati, si usa un diverso approccio

A. Poggi

60

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 1: Uso dellelemento component

Lelemento XML component serve per mappare le propriet` a di una classe Java denita dallutente che:

non ` una classe di dominio e deve essere resa persistente nella stessa tabella sulla quale si denisce il mapping per la classe per la quale denisce il mapping lelemento padre dellelemento component (N.B. si pu` anche fare un uso annidato o dellelemento component) component pu` essere usato quando non si ha bisogno di o eettuare alcuna conversione di tipo

A. Poggi

61

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: classe Indirizzo


Ricordiamo che la classe User.java aveva una propriet` a indirizzo di tipo Indirizzo. La classe Indirizzo ` cos` e denita:
package bid; public class Indirizzo { private String via; private String cap; private int numeroCivico; private String citta; public Indirizzo(){} public String getVia() { return via;} public void setVia(String via) { this.via=via;} public String getCap() { return cap;}

A. Poggi

62

Progetto di Applicazioni Software

Anno accademico 2008-2009

public void setCap(String cap) { this.cap=cap;} public int getNumeroCivico() { return numeroCivico;} public void setNumeroCivico(int numero) { this.numeroCivico=numero;} public String getCitta() { return citta;} public void setCitta(String citta) { this.citta=citta;} }

A. Poggi

63

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: mapping della propriet` indirizzo a di tipo Indirizzo


Nel le di mapping User.hbm.xml mappiamo la propriet` a indirizzo come segue:
<hibernate-mapping> <class name="bid.User" table="UTENTE"> (...) <component name="indirizzo" class="bid.Indirizzo"> <property name="via" column="via"></property> <property name="numeroCivico" column="civico"></property> <property name="cap" column="cap"></property> <property name="citta" column="citta"></property> </component> </class> </hibernate-mapping>

A. Poggi

64

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 2: Uso dei Custom types di Hibernate

Hibernate permette di denire dei tipi Hibernate ad-hoc nei casi in cui i tipi built-in non siano adeguati

sono fornite diverse interfacce pi` o meno complesse a u seconda del tipo di conversione da eettuare ` necessario denire una classe Java che implementa e una delle interfacce e che eettua la conversione da/verso valori della classe Java che realizza il tipo verso/da valori nella base di dati linterfaccia pi` comunemente usata ` u e org.hibernate.usertype.UserType: fornisce i metodi di base per eettuare il caricamento ed il salvataggio di istanze di classi che realizzano tipi di dato
A. Poggi 65

Progetto di Applicazioni Software

Anno accademico 2008-2009

unaltra interfaccia ` e org.hibernate.usertype.CompositeUserType: fornisce inoltre metodi per esporre/modicare propriet` a interne di istanze di classi che realizzano tipi UML non rientra negli scopi del corso

A. Poggi

66

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfaccia org.hibernate.usertype.UserType (Esempio)

Supponiamo che per le propriet` giornoInizio e a giornoFine della classe di dominio Item, si decida di evitare luso del tipo java.sql.Date e si voglia piuttosto usare il tipo GregorianCalendar si deve denire una classe che eettua la conversione dal tipo sql DATE degli attributi inizio e fine della tabella ITEM al tipo GregorianCalendar

A. Poggi

67

Progetto di Applicazioni Software

Anno accademico 2008-2009

Nel le di mapping Item.hbm.xml si denisce come mappare le propriet` si cui sopra come segue: a
<hibernate-mapping> <class name="bid.Item" table="ITEM"> (...) <property name="giornoInizio" column="inizio" type="persistence.GregorianCalendarUserType"/> <property name="giornoFine" column="fine" type="persistence.GregorianCalendarUserType"/> </class> </hibernate-mapping>

A. Poggi

68

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: classe che implementa un nuovo tipo di Hibernate


Implementiamo la classe persistence.GregorianCalendarUserType che realizza il nuovo tipo di Hibernate per fare la conversione da/verso GregorianCalendar ed il tipo SQL DATE
package persistence; import import import import import java.io.Serializable; java.sql.PreparedStatement; java.sql.ResultSet; java.sql.SQLException; java.util.*;

import org.hibernate.*; import org.hibernate.usertype.*;

A. Poggi

69

Progetto di Applicazioni Software

Anno accademico 2008-2009

public class GregorianCalendarUserType implements UserType{

//indica ad Hibernate i tipi SQL da mappare - possono essere pi` di uno u public int[] sqlTypes(){ return new int[] {Hibernate.DATE.sqlType()}; } //indica ad Hibernate il tipo Java da mappare public Class returnedClass() { return GregorianCalendar.class; } //indica se il tipo Java ` immutabile e //utile per effettuare eventuali ottimizzazioni public boolean isMutable() { return false; } //per eseguire il dirty checking, il tipo Hibernate usa i seguenti //metodi, che tipicamente delegano ai metodi corrispondenti del tipo Jav public boolean equals(Object x, Object y) throws HibernateException { if (x==y) return true; if (x==null || y==null) return false; return x.equals(y);

A. Poggi

70

Progetto di Applicazioni Software

Anno accademico 2008-2009

} public int hashCode(Object x) throws HibernateException { return x.hashCode(); } //restituisce una copia del valore del tipo Java - se il tipo //` immutabile, ` sufficiente restituire il riferimento alloggetto e e public Object deepCopy(Object value) throws HibernateException { if (value==null) return value; else { GregorianCalendar g= (GregorianCalendar) ((GregorianCalendar) value).clone(); return g; } } //metodo che converte e restituisce i valori ottenuti dal JDBC //ResultSet nel valore della propriet` Java corrispondente a public Object nullSafeGet(ResultSet resultSet, String[] names, Object ow throws HibernateException,SQLException { String s = resultSet.getDate(names[0]).toString(); int year=Integer.parseInt(s.substring(0,4));

A. Poggi

71

Progetto di Applicazioni Software

Anno accademico 2008-2009

int month=Integer.parseInt(s.substring(5,7)); int day=Integer.parseInt(s.substring(8,10)); return new GregorianCalendar(year,month,day); } //metodo che converte e scrive il valore della propriet` Java del a //tipo sul JDBC PreparedStatement che esegue il salvataggio public void nullSafeSet(PreparedStatement statement, Object value, int i throws HibernateException, SQLException { if (value==null){ statement.setNull(index,Hibernate.DATE.sqlType()); } else { GregorianCalendar g= (GregorianCalendar) value; String s = g.get(Calendar.YEAR)+"-"+g.get(Calendar.MONTH)+"-"+ g.get(Calendar.DAY_OF_MONTH); statement.setDate(index,java.sql.Date.valueOf(s)); } } //metodo chiamato per effettuare il merge di ogetti in stato //"detached" - cf. lezione pi` avanti - se il tipo u //` immutabile, ` sufficiente restituire il riferimento alloggetto e e

A. Poggi

72

Progetto di Applicazioni Software

Anno accademico 2008-2009

public Object replace(Object original, Object target, Object owner) throws HibernateException { return deepCopy(original); } //metodi chiamati per usare il secondo livello di cache //in questo corso ignoriamo il secondo livello di cache, pertanto //questi metodi saranno sempre definiti come segue public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } public Serializable disassemble(Object value) throws HibernateException { return (Serializable) value; } }

A. Poggi

73

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare propriet` che sono valori con a molteplicit` massima diversa da 1 a


Quando si ha una propriet` P persistente di una classe di a dominio D che ` una collezione omogenea (Set, e List,Map...) di valori gestiti da unaltra tabella TABP, allora nel le di mapping di D si denisce un elemento apposito Noi vedremo come mappare Set e List, si rimanda alla doc per gli altri tipi di collezioni omogenee

A. Poggi

74

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare un attributo di tipo Set

Si usa lelemento set:

<set name="P" table="TABP"> <key column="IDD"/> <element type="TypeP" column="ColumnP"/> </set>


dove:

IDD ` lattributo di TABP che identica listanza di D per e la quale si denisce il mapping ColumnP ` la colonna di TABP che contiene i valori della e collezione mappati

A. Poggi

75

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare un attributo di tipo List

Si usa lelemento list:

<list name="P" table="TABP"> <key column="IDD"/> <list-index column="POSITION"/> <element type="TypeP" column="ColumnP"/> </list>

dove POSITION ` lattributo di TABP che contiene il valore e dellindice della lista

A. Poggi

76

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare propriet` che realizzano associazioni a

In linea di principio, Hibernate permette di mappare tutte le realizzazioni di associazioni in Java

propriet` riferimento ad unistanza di unaltra classe a persistente propriet` insieme di riferimenti ad istanze di unaltra a classe propriet` riferimento ad unistanza di una classe a TipoLink propriet` insieme di riferimenti ad istanze di una classe a TipoLink

A. Poggi

77

Progetto di Applicazioni Software

Anno accademico 2008-2009

Propriet` riferimento ad unistanza di unaltra a classe persistente


Consideriamo il caso di due classi di dominio A e B persistenti legate da unassociazione R senza attributi, con molteplicit` 0..1 o 1..1, sulla quale solo A ha responsabilit` a a la realizzazione in Java della classe A porta ad una propriet` P ropB che ` un riferimento ad unistanza della a e classe B . Indichiamo con TabA e TabB rispettivamente le tabelle su cui sono mappate A e B .

A. Poggi

78

Progetto di Applicazioni Software

Anno accademico 2008-2009

Ci sono 2 casi:

Caso 1: TabA ha accorpato la relazione ER corrispondente a R in TabA sar` denito un vincolo di foreign key verso a TabB
Si usa lelemento one-to-one:

<one-to-one name="PropB" class="B"/>

A. Poggi

79

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 2: la relazione ER corrispondente a R ha portato ad una tabella T abR T abR ha due foreign key FKA, FKB verso le tabelle su cui sono mappate A e B , rispettivamente
Si usa lelemento join:

<join table="TabR"> <key column="FKA"/> <many-to-one name="PropB" class="B" column="FKB"/> </join>

A. Poggi

80

Progetto di Applicazioni Software

Anno accademico 2008-2009

Propriet` insieme di riferimenti ad istanze di a unaltra classe persistente


Consideriamo il caso di due classi di dominio A e B persistenti legate da unassociazione R senza attributi, con molteplicit` 0.. o 1.., sulla quale solo A ha responsabilit` a a

A. Poggi

81

Progetto di Applicazioni Software

Anno accademico 2008-2009

Anche in questo caso, due casi sono possibili:

Caso 1: TabB ha accorpato la relazione ER corrispondente a R in TabB ` denita una foreign key FKA verso TabA e
Si usa lelemento set:

<set table="TabB" optional="true"> <key column="FKA"/> <one-to-many class="B"/> </join>


N.B. In questo caso assumiamo che la chiave primaria di TabB sia la chiave primaria di TabA - attenzione: se la chiave primaria di TabB ` contenuta nella chiave nella e chiave primaria di TabA, allora Hibernate permette ad implementare il mapping
A. Poggi 82

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 2: la relazione ER corrispondente a R ha portato ad una tabella T ABR T abR ha due foreign key FKA, FKB verso le tabelle su cui sono mappate A e B , rispettivamente
Si usa anche questa volta lelemento join:

<join table="TabR" optional="true"> <key column="FKA"/> <many-to-one name="PropB" class="B" column="FKB"/> </join>

A. Poggi

83

Progetto di Applicazioni Software

Anno accademico 2008-2009

Cascading di oggetti
Quando una classe A ha responsabilit` su di unassociazione a AB con B , Hibernate fornisce la possibilit` di richiedere che a una qualsiasi operazione di persistenza su A sia transitiva es. il salvataggio di un oggetto di A, implichi il salvataggio delloggetto di B associato ad A Si denisce uguale ad "all" lattributo cascade dellelemento XML che denisce il mapping per lassociazione per indicare ad Hibernate che tutte le operazioni devono essere persistenti (altrimenti si usa il nome delloperazione, e.g. "save-update") Attenzione: Nel caso del delete transitivo, bisogna fare attenzione a non lasciare dei riferimenti ad oggetti appesi (cf. corso di Progettazione del software)
A. Poggi 84

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso in cui si ha una classe di tipo TipoLink


Siano A e B due classi di dominio persistenti legate da unassociazione R con attributi, tali che:

R ha un attributo e/o A e B hanno entrambe responsabilit` su R a la realizzazione in Java porta ad una classe java T ipoLinkAB che realizza il link tra le istanze di A e B , ed ad una classe java che realizza A e ha ad una propriet` P ropB a che ` un riferimento ad unistanza della classe T ipoLinkAB e Idea: mappiamo anche la classe T ipoLinkAB con laccortezza di usare un identicatore composto sia dallidenticatore di A che dallidenticatore B
A. Poggi 85

Progetto di Applicazioni Software

Anno accademico 2008-2009

Link mappati pi` volte u

Quando si mappa pi` volte lo stesso link tra oggetti di u classi java, il mapping indica a Hibernate di eettuare la stessa operazione di persistenza pi` volte u si possono ottenere delle violazioni di chiave! Si sceglie un verso per il link, e si denisce uguale a "true" lattributo inverse del mapping che specica come mappare il link nellaltro verso. Esempio: caso delle classi TipoLink

A. Poggi

86

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare gerarchie

Supponiamo di avere una generalizzazione completa, tale che due classi A e B specializzano G, rispettivamente mappate sulle tabelle TabA, TabB e TabG, tali che TabA e TabB abbiano entrambe una foreign key FKA e FKB verso TabG Si denisce il mapping per G, denendo come mappare, oltre alle propriet` di G, anche le propriet` delle sue a a sottoclassi A e B .

A. Poggi

87

Progetto di Applicazioni Software

Anno accademico 2008-2009

Si usa lelemento joined-subclass:

<joined-subclass name="A" table="TabA"> <key column="FKA"/> (...) </joined-subclass>

A. Poggi

88

Progetto di Applicazioni Software

Anno accademico 2008-2009

Note importanti sul mapping di gerarchie


Il mapping descritto si pu` usare SOLO nel caso in cui o la gerarchia sia completa Allinterno di uno stesso le di mapping non si possono usare due elementi joined-subclass e join allo stesso livello In molti casi di gerarchie, non si pu` usare Hibernate ma o si deve ricorrere allapproccio DAO

A. Poggi

89

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il ciclo di vita degli oggetti

A. Poggi

90

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il ciclo di vita degli oggetti persistenti

Unapplicazione orientata agli oggetti che fa uso di un meccanismo di persistenza deve interagire con il servizio di persistenza ogni volta che ha bisogno di propagare lo stato di un oggetto in memoria sulla base di dati

lo stato di un oggetto che appartiene ad una classe persistente cambia a seconda delloperazione del servizio di persistenza che viene invocata

A. Poggi

91

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il ciclo di vita degli oggetti delle classi persistenti


Transiente save() saveOrUpdate() garbage

new

Rimosso delete()

Persistente evict() close() clear() update() saveOrUpdate() merge()

Staccato

garbage

A. Poggi

92

Progetto di Applicazioni Software

Anno accademico 2008-2009

Lo stato transiente
un oggetto creato con unoperazione new entra nello stato transiente, in quanto non ` (ancora) associato e con alcuna tupla della base di dati la vita di un oggetto nello stato transiente termina non appena non esiste pi` alcun oggetto che fa riferimento u ad esso (diventa disponibile per il servizio di garbage collection) Hibernate non fornisce alcun servizio di roll-back per gli oggetti nello stato transiente

A. Poggi

93

Progetto di Applicazioni Software

Anno accademico 2008-2009

Lo stato persistente
un oggetto nello stato persistente ` un oggetto che ha e associato un identicatore proveniente dalla base di dati un oggetto nello stato persistente ` sempre associato e ad un contesto di persistenza, ovvero ad un insieme di oggetti dellapplicazione sincronizzati rispetto alla base di dati il contesto di persistenza pu` essere considerato o come una cache di istanze associata allistanza sessione (istanza di Session) correntemente aperta: quando la sessione viene chiusa, la cache viene svuotata

A. Poggi

94

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il contesto di persistenza
il contesto di persistenza ` utile ai seguenti ni: e
per fare automatic dirty checking: quando il contesto di persistenza ` chiuso, lo stato della cache e ` propagato alla base di dati in maniera e transazionale tutte e sole le propriet` degli oggetti persistenti a che sono state modicate saranno aggiornate per fare write-behind: modiche agli oggetti nel contesto di persistenza sono propagate alla base di dati allinvocazione del metodo flush ottimizza gli accessi e riduce la durata del lock sul database
A. Poggi 95

Progetto di Applicazioni Software

Anno accademico 2008-2009

per realizzare un raggio dellapplicazione allinterno del quale gli oggetti coinvolti sono tra loro consistenti, in modo tale da garantire (i) lidentit` a degli oggetti (i.e., una tupla di valori della base di dati ` associata al pi` ad un oggetto), (ii) il e u repeatable read per ottimizzare gli accessi, realizzando a tutti gli eetti una cache di primo livello

A. Poggi

96

Progetto di Applicazioni Software

Anno accademico 2008-2009

Transazioni e Session
Allapertura di un nuovo oggetto della classe Session (metodo openSession() della classe SessionFactory) viene creata una nuova connessione JDBC con la base di dati di default, Hibernate imposta lautocommit a false, il che comincia a tutti gli eetti una transazione JDBC!

A. Poggi

97

Progetto di Applicazioni Software

Anno accademico 2008-2009

quando viene invocato il metodo flush le modiche nel contesto di persistenza sono sincronizzate con la base di dati Attenzione: non viene eseguito commit, quindi lesito della transazione dipende dal DBMS sottostante ` necessario usare la classe transaction, con i suoi e metodi commit sia rollback N.B. Di default, il ushing della sessione avviene implicitamente al quando viene invocato il commit e prima di eseguire una query

A. Poggi

98

Progetto di Applicazioni Software

Anno accademico 2008-2009

Locking ottimistico di sessione


in caso di accesso concorrente, anch non occorrano e anomalie di tipo lost-update, Hibernate prevede la possibilit` di abilitare un meccanismo di locking a ottimistico tale che nel momento in cui viene invocato il ushing, verica se la porzione della base di dati che sar` modicata non sia cambiata a se ` cambiata lancia uneccezione e StaleObjectStateException per abilitare il locking ottimistico, nellelemento class del le di mapping relativo alla classe su cui verte la modica, ` necessario denire lattributo e optimistic-lock pari ad all
A. Poggi 99

Progetto di Applicazioni Software

Anno accademico 2008-2009

Rendere un oggetto persistente


un oggetto entra nello stato persistente:
dopo che sulloggetto nello stato transiente ` e invocato uno dei metodi save/saveOrUpdate
Session (Contesto di persistenza) openSession()

new(O)

save(o) saveOrUpdate(o)

N.B. Il metodo saveOrUpdate verica prima se loggetto occorre nella base di dati ed a seconda dellesito della verica, eettua unoperazione di INSERT o di UPDATE

A. Poggi

100

Progetto di Applicazioni Software

Anno accademico 2008-2009

quando viene creato (i) invocando uno dei metodi get e load del servizio di persistenza, (ii) come risultato di una query, (iii) navigando il grafo degli oggetti a partire da unaltra istanza persistente
Session (Contesto di persistenza) openSession()

new(O)

save(o) saveOrUpdate(o)

N.B. I due metodi get e load si distinguono per il fatto che se lidenticatore non viene trovato, get restituisce null mentre load lancia una ObjectNotFoundException

A. Poggi

101

Progetto di Applicazioni Software

Anno accademico 2008-2009

Lo stato staccato
un oggetto ` nello stato staccato se era nello stato e persistente ed ` stato poi cancellato dal contesto di e persistenza il riferimento alloggetto rimane ma pu`: o
divenire obsoleto a seguito di cambiamenti sulla base di dati non essere pi` sincronizzato con i valori ad esso u associati nella base di dati`, in quanto lapplicazione e stessa pu` modicare alcune sue propriet` o a

A. Poggi

102

Progetto di Applicazioni Software

Anno accademico 2008-2009

un oggetto pu` essere reso staccato invocando uno tra o i metodi evict/ clear (che appunto cancellano listanza/tutte le istanze dalla cache del contesto di persistenza) alla chiusura della sessione, un oggetto entra nello stato staccato
Session (Contesto di persistenza) openSession() flush() close()

new(O)

save(o) saveOrUpdate(o)

A. Poggi

103

Progetto di Applicazioni Software

Anno accademico 2008-2009

un oggetto nello stato staccato pu` tornare ad entrare o nello stato persistente attraverso linvocazione dei metodi update/saveOrUpdate
Session (Contesto di persistenza) openSession() flush() close()

update(o) saveOrUpdate(o)

setValue(v)

A. Poggi

104

Progetto di Applicazioni Software

Anno accademico 2008-2009

quando si vuole fare tornare ad essere persistente un oggetto che ` nello stato staccato ed esiste gi` e a unistanza persistente corrispondente alla stessa tupla della base di dati, si invoca il metodo merge, che copia le propriet` delloggetto staccato sulle propriet` a a delloggetto persistente corrispondente alla stessa tupla della base di dati
Session (Contesto di persistenza) openSession() flush() close()

object o

getid(id)

(copy properties(o,o)) object o S

merge(o)

A. Poggi

105

Progetto di Applicazioni Software

Anno accademico 2008-2009

Lo stato rimosso
un oggetto ` nello stato rimosso se era nello stato e persistente ed ` invocato il metodo delete e ` stato schedulato per essere rimosso al termine di e ununit` di lavoro, ma fa ancora parte del contesto di a persistenza nch lunit` di lavoro non ` completata e a e
Session (Contesto di persistenza) openSession() flush() close()

load(id)

delete(o)

A. Poggi

106

Progetto di Applicazioni Software

Anno accademico 2008-2009

un oggetto nello stato rimosso non deve essere riusato e devono essere rimossi tutti i riferimenti ad esso, in quanto sar` cancellato dalla base di dati a appena lunit` di lavoro sar` completata a a un oggetto nello stato rimosso diventa disponibile per il servizio di garbage collection al termine dellunit` di a lavoro

A. Poggi

107

Progetto di Applicazioni Software

Anno accademico 2008-2009

Long-lived transactions
richiamo: tra il momento in cui si leggono i dati dal DB ed il momento in cui eventuali modiche si rendono persistenti pu` trascorrere molto tempo o si applica il pattern session-per-conversation: ` e necessario disabilitare il ushing automatico chiamando il metodo setFlushMode(FlushMode.MANUAL) quando la sessione ` aperta e

A. Poggi

108

Progetto di Applicazioni Software

Anno accademico 2008-2009

lisolamento ` garantito in quanto, abilitando il e locking ottimistico, le modiche fatte in transazioni concorrenti sono riconosciute latomicit` ` garantita dal fatto che il ushing viene a e eseguito solo al termine della transazione, e se la sessione viene chiusa senza fare il ushing, la transazione viene abortita

A. Poggi

109

Progetto di Applicazioni Software

Anno accademico 2008-2009

Nota sui servizi che accedono direttamente alla base di dati


come gi` visto nellapproccio DAO, a volte ` necessario a e accedere direttamente alla base di dati per mezzo di query SQL (senza passare dagli oggetti delle classi mappate) il principale vantaggio che ore Hibernate ` la e conversione automatica di un result set in oggetti della base di dati

A. Poggi

110

Progetto di Applicazioni Software

Anno accademico 2008-2009

List result = session. createSQLQuery("SELECT * FROM CATEGORY"). addEntity(Category.Class).list();

Hibernate legge il result set e sulla base del le di mapping denito per la classe Category, analizza le colonne restituite: per ogni colonna restituita, verica se ` mappata su di una propriet` della classe, e se lo `, e a e popola la suddetta propriet` e restituisce una lista di a oggetti caricati dalla base di dati Attenzione: questo meccanismo funziona correttamente solo se si usano delle query SQL semplici come quella su specicata...

A. Poggi

111

Progetto di Applicazioni Software

Anno accademico 2008-2009

Realizzare un livello di persistenza generico

A. Poggi

112

Progetto di Applicazioni Software

Anno accademico 2008-2009

Perch un livello di persistenza generico? e


permette di astrarre dalla tecnologia ORM usata e di fornire un livello di astrazione maggiore, concentrato sui servizi ad alto livello forniti dal livello di persistenza permette di nascondere al client limplementazione eettiva del livello di persistenza permette di far coesistere approcci misti allORM, i.e. Hibernate e lapproccio DAO hand-coded

A. Poggi

113

Progetto di Applicazioni Software

Anno accademico 2008-2009

Pattern DAO con interfacciamento generico

Il pattern di programmazione che useremo prevede la denzione di uninterfaccia che comprende tutte le operazioni di persistenza di base (CRUD e metodi di ricerca) necessarie per ogni classe persistente

A. Poggi

114

Progetto di Applicazioni Software

Anno accademico 2008-2009

GenericDAO<T,ID> findById(ID id) makePersistent() makeTransient() GenericDAOHibernate<T,ID> GenericDAOMio<T,ID>

GenericItemDAO<Item,int> CalcolaTempoResiduo() GenericDAOHibernate<T,ID>

GenericDAOHibernate<T,ID>

GenericUserDAO<Item,int> GenericDAOHibernate<T,ID>

GenericDAOHibernate<T,ID>

A. Poggi

115

Progetto di Applicazioni Software

Anno accademico 2008-2009

Generica super-interfaccia
Raggruppa tutte le operazioni CRUD di base condivise da tutte le classi persistenti
public interface GenericDAO<T,ID extends Serializable> { T findById(ID id); T makePersistent(T class); void makeTransient(T class); }

Eventualmente, pu` comprendere i metodi flush e clear. o

A. Poggi

116

Progetto di Applicazioni Software

Anno accademico 2008-2009

Generica implementazione con Hibernate


Una possibile implementazione della super-interfaccia generica usa Hibernate, ovvero include propriet` speciche a di un livello di persistenza realizzato con Hibernate condivise da tutte le classi la cui persistenza ` realizzata e con Hibernate
public abstract class GenericDAOHibernate<T,ID extends Serializable> implements GenericDAO<T, ID estends Serializable> { private Class<T> persistentClass; private Session session; public GenericDAOHibernate(){ this.persistentClass= (Class<T>) (ParameterizedType) getClass().getGenericSuperClass()) .getActualTypeArguments().[0]; }

A. Poggi

117

Progetto di Applicazioni Software

Anno accademico 2008-2009

public void setSession (Session s) { this.session = s; } protected Session openSession(){ if (session==null) session = HibernateUtil.getSessionFactory(). openSession(); return session; } protected Session getSession(){ if (session==null) session = HibernateUtil.getSessionFactory(). getCurrentSession(); return session; } public Class<T> getPersistentClass(){ return persistentClass; } public T findById(ID is) { T class = (T) getSession.load(getPersistentClass(),id);

A. Poggi

118

Progetto di Applicazioni Software

Anno accademico 2008-2009

return class; } public T makePersistent(T class) { getSession.saveOrUpdate(class); return class; } public void makeTransient(T class) { getSession.delete(class); } public void flush() { getSession.flush(); } public void clear() { getSession.clear(); } }

A. Poggi

119

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfacciamento specico delle classi persistenti


Per ogni classe persistente, si denisce una sotto-interfaccia che comprende i metodi specici della classe
public interface ItemDAO extends GenericDAO<Item,int> { int CalcolaTempoResiduo(); }

A. Poggi

120

Progetto di Applicazioni Software

Anno accademico 2008-2009

Implementazione di classi persistenti con Hibernate


Rimangono da denire le sottoclassi dellimplementazione generica con Hibernate, che implementano linterfaccia specica di ogni classe persistente
public class ItemDAOHibernate extends GenericDAOHibernate<Item, int> implements ItemDAO { public int CalcolaTempoResiduo(){ (...) } }

A. Poggi

121

Progetto di Applicazioni Software

Anno accademico 2008-2009

Nota

Per realizzare unimplementazione che segue lapproccio DAO hand-coded ` necassario allo stesso modo, denire e unimplementazione generica e una sua sottoclasse per ogni classe persistente cf. lezione sullapproccio DAO allORM

A. Poggi

122

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio di uso del livello di persistenza


Quando si deve creare un oggetto della classe persistente, ` e necessario fare riferimento allimplementazione usata
ItemDAO itemDAO = new ItemDAOHibernate(); UserDAO userDAO =new UserDAOMio(); Item item = itemDAO.findById(itemId); (...) }

A. Poggi

123