Sei sulla pagina 1di 124

Introduzione a Hibernate

Versione preliminare

Antonella Poggi

Dipartimento di informatica e Sistemistica Sapienza Universit`a di Roma

Progetto di Applicazioni Software Anno accademico 2008-2009

Progetto di Applicazioni Software

Anno accademico 2008-2009

Riferimenti bibliografici

Anno accademico 2008-2009 Riferimenti bibliografici • Libro “Java Persistence with Hibernate”, Christian

Libro “Java Persistence with Hibernate”, Christian Bauer and Gavin King - Editore: Manning

Hibernate Reference Documentation (cf. link sulla pagina web del corso)

Progetto di Applicazioni Software

Anno accademico 2008-2009

Argomenti principali

Software Anno accademico 2008-2009 Argomenti principali • Introduzione ad Hibernate e suoi principali utilizzi

Introduzione ad Hibernate e suoi principali utilizzi

Le basi della gestione della persistenza con Hibernate

Mapping pi`u complessi

Le transazioni e il ciclo di vita degli oggetti

Creare un livello generico per la gestione della persistenza

Progetto di Applicazioni Software

Anno accademico 2008-2009

Introduzione ad Hibernate e suoi principali utilizzi

Progetto di Applicazioni Software

Hibernate core

Anno accademico 2008-2009

Software Hibernate core Anno accademico 2008-2009 • Anche noto come Hibernate o Hibernate 3.3.x •

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`a di interrogare la basi di dati

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il codice dell’applicazione usa le API di Hibernate per gestire la persistenza

I mapping tra classi Java e tabelle relazionali sono specificati in appositi file XML in linea di principio, lo sviluppatore `e esonerato da:

richieste di esecuzione di chiamate SQL

gestione manuale dei risultati di chiamate SQL e loro eventuale conversione in oggetti

L’applicazione rimane portabile in tutti i sistemi di gestione supportati, con pochissimo overhead

Pu`o essere usato in maniera independente dal tipo di applicazione, di piattaforma e di ambiente runtime, con tutti i JDK

Progetto di Applicazioni Software

Hibernate tools

Anno accademico 2008-2009

Software Hibernate tools Anno accademico 2008-2009 • Insieme di strumenti per Hibernate 3 • Forniscono

Insieme di strumenti per Hibernate 3

Forniscono dei task Ant e dei plugin Eclipse per fare reverse engineering, generazione di codice, e, pi`u in 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 flessibile

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate

Anno accademico 2008-2009 Tipici utilizzi di Hibernate • Top down • Bottom up • Meet in

Top down

Bottom up

Meet in the middle

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Top Down

accademico 2008-2009 Tipici utilizzi di Hibernate: Top Down • Si parte da un diagramma delle classi

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 specificano i file XML con i mapping ed eventualmente, si pu`o usare Hibernate (in particolare lo strumento Hibernate hbm2ddl) per generare lo schema della base di dati

vantaggi: comodo quando non vi `e alcun database preesistente

svantaggi: diventa laborioso se si vogliono sfruttare tutte le caratteristiche del DBMS, e.g. stored procedure, trigger

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Bottom up

accademico 2008-2009 Tipici utilizzi di Hibernate: Bottom up • Si parte da un base di dati

Si parte da un base di dati esistente legacy e si ha completa libert`a rispetto al dominio dell’applicazione

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 file XML

dei mapping

hbm2cfgxml:

strumento che prende in ingresso i

Progetto di Applicazioni Software

Anno accademico 2008-2009

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

Problemi:

lo

schema della base di dati deriva, nella migliore

delle ipotesi, da un “degrado” dello schema ER non si potr`a mai ottenere un diagramma delle classi che sfrutti caratteristiche importanti della

programmazione ad oggetti, e.g. ereditariet`a, polimorfismo

la

logica dell’applicazione `e influenzata dalla

rappresentazione dei dati il diagramma delle classi

di dominio conterr`a solamente le classi persistenti

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipici utilizzi di Hibernate: Meet in the middle

2008-2009 Tipici utilizzi di Hibernate: Meet in the middle • Scenario pi`u interessante e comune -

Scenario pi`u interessante e comune - quello del progetto richiesto per questo corso!

Si parte da un diagramma delle classi di dominio dell’applicazione e da una base di dati preesistente

Non `e in generale possibile mappare un insieme di classi di dominio su di una base di dati arbitrari si deve seguire un approccio generico all’ORM e ricorrere ad Hibernate quando possibile, ed in caso contrario, all’approccio generico DAO

N.B. Nella trattazione che faremo, assumeremo di usare Hibernate seguendo l’approccio “Meet in the middle”.

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le basi della gestione della persistenza con Hibernate

Progetto di Applicazioni Software

Anno accademico 2008-2009

Hibernate in azione

Software Anno accademico 2008-2009 Hibernate in azione 5 principali ingredienti di un’applicazione che fa uso di

5 principali ingredienti di un’applicazione 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 file che definisce il mapping di ogni classe persistente

uno o pi`u file di configurazione di Hibernate

le interfacce Hibernate per l’accesso alla base di dati:

Session, Transaction e Query - package org.hibernate

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le classi di dominio

Software Anno accademico 2008-2009 Le classi di dominio • Le classi di dominio sono definite come

Le classi di dominio sono definite come in qualsiasi applicazione Java tipicamente, metodi set e get per l’accesso in scrittura e lettura delle propriet`a degli oggetti della classe

metodi di business della classe

Progetto di Applicazioni Software

Anno accademico 2008-2009

Diagramma delle classi di dominio - Esempio

2008-2009 Diagramma delle classi di dominio - Esempio 0 1 Offerta ammontare : int dataCreazione: Date

0

1

Offerta

ammontare : int dataCreazione: Date

0

*

vincente

0

*

relativa

Item

nome : String codice : int descrizione : String prezzoIniziale: int giornoInizio: Date giornoFine: Date

calcolaTempoRes-

iduo(): int

0

fattaDa

User

nome : String cognome : String username: String password: String email: String

calcolaCostoSpedi

zione(): int

Indirizzo

via : String civico : int cap: String città: String

risiede

*

compratoDa

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le classi di dominio - Esempio

Anno accademico 2008-2009 Le classi di dominio - Esempio package bid; import java.util.StringTokenizer;

package

bid;

import

java.util.StringTokenizer;

public

class

User

{

private

String

nome;

private

String

cognome;

private

String

username;

private

String

password;

private

String

email;

private

Indirizzo

indirizzo;

public

User(){}

public

User(String

user){

username=user;

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

 

{

Progetto di Applicazioni Software

Anno accademico 2008-2009

//

funzione

che

restituisce

il

costo

della

spedizione

}

}

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di un’applicazione che usa Hibernate(1)

il codice di un’applicazione che usa Hibernate(1) WORKDIR + lib <Hibernate + src ed +bid User.java

WORKDIR

+ lib

<Hibernate

+ src

ed

+bid

User.java

+ bin

altre

librerie>

Progetto di Applicazioni Software

La base di dati

Anno accademico 2008-2009

Software La base di dati Anno accademico 2008-2009 ` • costituita da un insieme di: E

`

costituita da un insieme di:

E

tabelle

vincoli

store procedure, trigger

`

mantenuta all’interno di un certo DBMS, e.g. Mysql,

E

provvisto del proprio driver jdbc

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

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tabelle della base di dati - Esempio

accademico 2008-2009 Tabelle della base di dati - Esempio CREATE username nome TABLE utente VARCHAR(10) VARCHAR(15),

CREATE

username

nome

TABLE

utente

VARCHAR(10)

VARCHAR(15),

(

PRIMARY

KEY,

cognome

VARCHAR(15),

cod_fis

VARCHAR(16)

UNIQUE,

password

VARCHAR(8),

email

via

civico

cap

citta

VARCHAR(20),

VARCHAR(20),

INT,

VARCHAR(5),

VARCHAR(15));

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping per le classi persistenti

2008-2009 File di mapping per le classi persistenti • File XML che definisce come si mappano

File XML che definisce come si mappano le propriet`a delle classi Java persistenti sulle tabelle della base di dati

Deve soddisfare la grammatica specificata all’interno di un apposito DTD, chiamato

hibernate-mapping-3.0.dtd

N.B. Per verificare la correttezza sintattica del file XML, Hibernate cercher`a il DTD all’interno del classpath e lo trover`a nella libreria .jar di Hibernate (ammesso che il classpath la includa) - qualora non dovesse trovare il DTD, Hibernate lo cercher`a all’indirizzo specificato nella dichiarazione del DOCTYPE

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping - Esempio

Software Anno accademico 2008-2009 File di mapping - Esempio File User.hbm.xml <?xml <!DOCTYPE

File User.hbm.xml

<?xml

<!DOCTYPE

version="1.0"?>

hibernate-mapping

PUBLIC

"-//Hibernate/Hibernate

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

Mapping

DTD

3.0//EN"

<hibernate-mapping>

<class

name="User"

table="UTENTE">

<id

<property

<property

<property

<property

name="username"

column="username"></id>

name="nome"

name="cognome"

name="email"></property>

name="password"></property>

column="NOME"></property>

column="COGNOME"></property>

</class>

</hibernate-mapping>

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di mapping - Commenti

Anno accademico 2008-2009 File di mapping - Commenti • L’elemento class dichiara il nome della classe

L’elemento 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 `e rappresentata da una tupla della tabella

L’elemento id dichiara:

il nome della propriet`a della classe che gioca il ruolo di identificatore Importante:

una classe persistente `e sempre caratterizzata da una propriet`a che ne identifica le istanze

una volta creato un oggetto della classe, tale

Progetto di Applicazioni Software

Anno accademico 2008-2009

propriet`a non potr`a essere modificata dall’applicazione (il corrispondente metodo set pu`o essere definito privato)

il nome dell’attributo della tabella che identifica le tuple mappate su oggetti

L’elemento 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`a che identifica gli oggetti, il nome della propriet`a indica ad Hibernate quali metodi set e get usare

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di un’applicazione che usa Hibernate(2)

il codice di un’applicazione che usa Hibernate(2) WORKDIR + lib <Hibernate + src ed altre +

WORKDIR

+ lib

<Hibernate

+ src

ed

altre

+

User.java

User.hbm.xml

bid

+ bin

librerie>

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di configurazione per Hibernate

accademico 2008-2009 File di configurazione per Hibernate • Hibernate costituisce la parte dell’applicazione che

Hibernate costituisce la parte dell’applicazione che gestisce la persistenza, ovvero che si connette alla base di dati ha bisogno di avere le informazioni necessarie ad effettuare la connessione, quali il DBMS, il driver JDBC, la base di dati, utente/password, etc.

Un file XML fornisce tutte queste informazioni

Tale file deve soddisfare la grammatica specificata in

nel DTD hibernate-

configuration-3.0.dtd

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di configurazione per Hibernate - Esempio

2008-2009 File di configurazione per Hibernate - Esempio File hibernate.cfg.xml <?xml <!DOCTYPE

File hibernate.cfg.xml

<?xml

<!DOCTYPE

version="1.0"

encoding="UTF-8"?>

hibernate-configuration

PUBLIC

"-//Hibernate/Hibernate

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

Configuration

DTD

3.0//EN"

<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

-->

Progetto di Applicazioni Software

<property

name="dialect">

Anno accademico 2008-2009

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>

Progetto di Applicazioni Software

Anno accademico 2008-2009

File di configurazione per Hibernate - Commenti

2008-2009 File di configurazione per Hibernate - Commenti • L’elemento session-factory definisce le

L’elemento session-factory definisce le impostazioni per l’accesso ad una particolare base di dati

Le propriet`a il cui nome ha la forma

(hibernate).connection. * contengono le

informazioni necessarie per impostare la connessione JDBC

La propriet`a dialect specifica la variante di SQL che deve generare Hibernate

Le propriet`a c3p0. * indicano le impostazioni necessarie a configurare il software c3p0 per il pooling di connessioni

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`u usata viene rimossa

max statements:

numero di prepared statements

che sono mentenuti in cache

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di un’applicazione che usa Hibernate(3)

il codice di un’applicazione che usa Hibernate(3) WORKDIR + lib <Hibernate + src ed altre +

WORKDIR

+ lib

<Hibernate

+ src

ed

altre

+

User.java

User.hbm.xml

bid

hibernate.cfg.xml

+ bin

librerie>

Progetto di Applicazioni Software

Anno accademico 2008-2009

Le interfacce Hibernate

Software Anno accademico 2008-2009 Le interfacce Hibernate Hibernate fornisce tre principali interfacce per l’accesso

Hibernate fornisce tre principali interfacce per l’accesso 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 dell’applicazione: non `e necessario usare l’API JDBC per impostare una transazione

gioca al ruolo di gestore di transazioni in un sistema che accede a pi`u basi di dati all’interno di un’unica

unit`a di lavoro di sistema

Progetto di Applicazioni Software

Anno accademico 2008-2009

Query:

query

interfaccia che permette di creare ed eseguire

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 nell’approccio DAO

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfacce Hibernate - Esempio d’uso

accademico 2008-2009 Interfacce Hibernate - Esempio d’uso File Bid.java package bid; import java.util. *

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

tx.commit();

session.close();

userId

=

(String)

session.save(user);

Progetto di Applicazioni Software

Anno accademico 2008-2009

//Second

unit

of

work

session

=

HibernateUtil.getSessionFactory().openSession();

tx

user

user.setNome("Filippo");

tx.commit();

session.close();

=

session.beginTransaction();

=

(User)

session.get(User.class,userId);

//Third

unit

of

work

session

=

HibernateUtil.getSessionFactory().openSession();

tx

List

order

System.out.println(users.size()+"

=

session.beginTransaction()

users

=

session.createSQLQuery("select

*

from

utente

by

username").addEntity(User.class).list();

user(s)

found:

");

for

(Iterator

iter=

users.iterator();

iter.hasNext();

)

{

User

userId

=

(User)

iter.next();

System.out.println

}

tx.commit();

(userId.getNome());

Progetto di Applicazioni Software

session.close();

//Shutting

HibernateUtil.shutdown();

down

the

application

}

}

Anno accademico 2008-2009

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfacce Hibernate - Commenti

Anno accademico 2008-2009 Interfacce Hibernate - Commenti • L’utilizzo dell’interfaccia Transaction imposta

L’utilizzo dell’interfaccia Transaction imposta l’autocommit a false necessit`a di chiamare il metodo

commit

Tutti i comandi SQL sono generati a runtime (o eventualmente all’avvio dell’applicazione per tutti quei comandi “riusabili”)

La prima unit`a di lavoro, quando eseguita, corrisponde ad effettuare 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,

Progetto di Applicazioni Software

null,

null,

null,

Anno accademico 2008-2009

null,

null,

null);

La seconda unit`a di lavoro mostra l’abilit`a di Hibernate di:

caricare un oggetto dalla base di dati, a partire dalla classe di cui `e istanza e dal suo identificatore

il metodo get(Class,Serializable) restituisce

un’istanza della classe persistente data in input caratterizzata dall’identificatore in input, e null se la suddetta istanza non esiste N.B. Richiede sia definito il costruttore senza argomenti per la classe persistente

effettuare un dirty checking automatico: senza che sia richiesto esplicitamente di fare l’update dell’istanza, Hibernate si “accorge” delle modifiche apportate sulla propriet`a nome ed aggiorna

Progetto di Applicazioni Software

automaticamente la base di dati

Anno accademico 2008-2009

La terza unit`a di lavoro mostra come `e possibile “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 nell’approccio DAO, ovvero, essenzialmente, ai casi in cui `e necessario effettuare una ricerca sulla base di dati non di tipo “diretto”, e.g.

FindByCriteria

Progetto di Applicazioni Software

Anno accademico 2008-2009

Inizializzazione di Hibernate - SessionFactory

2008-2009 Inizializzazione di Hibernate - SessionFactory • Per inizializzare Hibernate, si costruisce un oggetto

Per inizializzare Hibernate, si costruisce un oggetto SessionFactory a partire da un oggetto

Configuration

un oggetto Configuration, sostanzialmente, rappresenta il file di configurazione di Hibernate

SessionFactory

configure().buildSessionFactory();

sessionFactory

=

new

Configuration().

quando new

Configuration() `e chiamato,

Hibernate cerca un file chiamato

hibernate.properties (cf. esercitazione) e tutte

le

impostazioni l`ı definite sono associate all’oggetto

di

Configuration

Progetto di Applicazioni Software

Anno accademico 2008-2009

quando configure() `e chiamato, Hibernate cerca il

file hibernate.cfg.xml

la locazione in cui Hibernate cerca i file suddetti `e quella specificata nel classpath se si vuole usare un’altra locazione la si deve specificare 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 `e buona prassi realizzare una classe HibernateUtil per l’inizializzazione di Hibernate e la gestione della singola istanza di SessionFactory

Progetto di Applicazioni Software

Anno accademico 2008-2009

Gestore delle sessioni - HibernateUtil

accademico 2008-2009 Gestore delle sessioni - HibernateUtil File HibernateUtil.java package persistence; import

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

{

}

catch

new

Configuration().configure().buildSessionFactory();

(HibernateException

ex)

{

throw

new

ExceptionInInitializerError(ex);

}

}

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

}

}

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come organizzare il codice di un’applicazione che usa Hibernate(4)

il codice di un’applicazione che usa Hibernate(4) WORKDIR + lib <Hibernate + src ed altre librerie>

WORKDIR

+ lib

<Hibernate

+ src

ed

altre

librerie>

+bid

User.java

User.hbm.xml

Bid.java

+

HibernateUtil.java

persistence

hibernate.cfg.xml

+ bin

Progetto di Applicazioni Software

Anno accademico 2008-2009

I mapping

Progetto di Applicazioni Software

In poche parole

Anno accademico 2008-2009

Software In poche parole Anno accademico 2008-2009 I file di mapping permettono di definire: • come

I file di mapping permettono di definire:

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 nell’approccio 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

Progetto di Applicazioni Software

Note importanti

Anno accademico 2008-2009

Software Note importanti Anno accademico 2008-2009 1. In questa trattazione, assumeremo che la porzione

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 `e mappata su una ed un’unica tabella

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 un’associazione sono mappate su due tabelle legate da una o pi`u catene di vincoli di foreign key/inclusione (che eventualmente coinvolgono ulteriori tabelle)

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 `e pertanto necessario ricorrere all’approccio DAO

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 definisce il metodo set come per gli altri tipi di campi - ma attenzione: lo si definisce 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)

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare una classe Java significa

Anno accademico 2008-2009 Mappare una classe Java significa • stabilire una corrispondenza tra le sue istanze

stabilire una corrispondenza tra le sue istanze e le tuple di una tabella della base di dati

mappare il suo identificatore

mappare le sue propriet`a persistenti

propriet`a che sono valori (eventualmente insiemi di attributi/valori, ovvero con molteplicit`a massima diversa da 1)

propriet`a che sono istanze di un’altra classe di dominio Java (eventualmente insiemi di istanze, ovvero con molteplicit`a massima diversa da 1)

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare gli identificatori delle classi di dominio

Mappare gli identificatori delle classi di dominio La propriet`a che identifica una classe `e una propriet`a

La propriet`a che identifica una classe `e una propriet`a “speciale”

non pu`o essere modificata una volta che `e stata assegnata ad un’istanza

dal punto di vista sintattico, una propriet`a che identifica una classe deve essere mappata attraverso l’elemento XML <id> (che DEVE essere definito)

Progetto di Applicazioni Software

Anno accademico 2008-2009

<id> pu`o avere un elemento figlio <generator> che DEVE un attributo class che specifica una classe Java che implementa l’interfaccia

org.hibernate.id.IdentifierGenerator e che

viene usata per generare identificatori unici; se tale classe prende dei parametri in ingresso, vengono specificati per mezzo di elementi figli param; Hibernate viene fornito con delle classi built-in per generare identificatori, tra le altre:

assigned significa che l’applicazione assegna l’identificatore all’istanza prima che sia chiamato il

metodo save - questo `e il comportamento di default se generator non compare

native:

usa i generatori di identificatori forniti dal

DBMS sottostante - mantiene il mapping portabile

Progetto di Applicazioni Software

Anno accademico 2008-2009

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

che sono valori con molteplicit`a massima pari a 1 Abbiamo gi`a visto come si definisce nel

Abbiamo gi`a visto come si definisce nel file di mapping come mappare una propriet`a di una classe che `e un valore Si usa l’elemento XML property

Ora diciamo qualcosa in pi`u sul sistema di tipi di Hibernate

Progetto di Applicazioni Software

Anno accademico 2008-2009

Il sistema di tipi di Hibernate

Anno accademico 2008-2009 Il sistema di tipi di Hibernate • I tipi di Hibernate sono di

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`o esserci pi`u tipi Hibernate per uno stesso 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 definire dei tipi appositi per effettuare conversioni “ad-hoc”

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipi primitivi di Hibernate: corrispondenze SQL-Java

Tipi primitivi di Hibernate: corrispondenze SQL-Java Tipo Hibernate Tipo SQL standard Tipo Java integer

Tipo Hibernate

Tipo SQL standard

Tipo Java

integer

INTEGER

int

or

java.lang.Integer

long

BIGINT

long

or

java.lang.Long

integer

SMALLINT

short

or

java.lang.Integer

float

FLOAT

float

or

java.lang.Float

double

DOUBLE

double

or

java.lang.Double

big_decimal

NUMERIC

java.math.BigDecimal

character

CHAR(1)

java.lang.String

string

VARCHAR

(

)

java.lang.String

byte

TINYINT

float

or

java.lang.Float

boolean

BIT

boolean

or

java.lang.Boolean

Progetto di Applicazioni Software

Anno accademico 2008-2009

Tipi di dati Hibernate sulle date e il tempo

2008-2009 Tipi di dati Hibernate sulle date e il tempo Tipo Hibernate Tipo SQL standard Tipo

Tipo Hibernate

Tipo SQL standard

Tipo Java

date

DATE

java.util.Date

or

java.sql.Date

time

TIME

java.util.Time

or

java.sql.Time

timestamp

TIMESTAMP

java.util.Timestamp

or

java.sql.Timestamp

calendar

TIMESTAMP

java.util.Calendar

 

calendar_date

DATE

java.util.Calendar

 

Progetto di Applicazioni Software

Anno accademico 2008-2009

Come usare i tipi di Hibernate nei mapping (Esempio)

Come usare i tipi di Hibernate nei mapping (Esempio) <class name="Item" table="ITEM"> ( )

<class

name="Item"

table="ITEM">

(

)

<property

name="giornoInizio"

column="INIZIO"/>

</class>

type="time"

N.B. Se non specifichiamo il tipo di Hibernate, allora Hibernate usa la reflection, ovvero risale al tipo Java della propriet`a giornoInizio della classe Item e assume un comportamento di default se abbiamo definito la propriet`a giornoInizio come di tipo java.util.Date, Hibernate cerca di convertirla nel

tipo TIMESTAMP (

= TIME)

Progetto di Applicazioni Software

Anno accademico 2008-2009

Classi che realizzano tipi UML

Anno accademico 2008-2009 Classi che realizzano tipi UML • A valle della fase di progetto, sono

A valle della fase di progetto, sono spesso individuati dei tipi UML che sono realizzati tramite classi Java, da importare o definite nell’applicazione stesse

Le istanze di una classe che realizza un tipo UML:

sono propriet`a di classi di dominio

non possono essere condivise

non sono identificate da nessuna propriet`a

Per le classi che realizzano un nuovo tipo UML, `e necessario ridefinire i metodi toString, equals(), hashCode() e, se qualche funzione della classe Java effettua side-effect, clone()

Progetto di Applicazioni Software

Anno accademico 2008-2009

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

di propriet`a istanze di una classe che realizza un tipo UML Ipotesi: come sempre, le colonne

Ipotesi: come sempre, le colonne da mappare appartengono alla stessa tabella su cui `e mappata la classe

A seconda che sia o no necessario effettuare una conversione od una forma di type checking tra i valori delle propriet`a della classe che realizza il tipo UML, ed il valore degli attributi della base di dati mappati, si usa un diverso approccio

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 1: Uso dell’elemento component

accademico 2008-2009 Caso 1: Uso dell’elemento component L’elemento XML component serve per mappare le propriet`a

L’elemento XML component serve per mappare le propriet`a di una classe Java definita dall’utente che:

non `e una classe di dominio

deve essere resa persistente nella stessa tabella sulla quale si definisce il mapping per la classe per la quale definisce il mapping l’elemento padre dell’elemento component (N.B. si pu`o anche fare un uso annidato dell’elemento component)

component pu`o essere usato quando non si ha bisogno di effettuare alcuna conversione di tipo

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: classe Indirizzo

Anno accademico 2008-2009 Esempio: classe Indirizzo Ricordiamo che la classe User.java aveva una propriet`a

Ricordiamo che la classe User.java aveva una propriet`a

indirizzo di tipo Indirizzo.

definita:

La classe Indirizzo `e cos`ı

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

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

}

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: mapping della propriet`a indirizzo

di tipo Indirizzo

mapping della propriet`a indirizzo di tipo Indirizzo Nel file di mapping User.hbm.xml mappiamo la propriet`a

Nel file 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

<property

<property

<property

</component>

</class>

name="via"

name="numeroCivico"

name="cap"

name="citta"

column="via"></property>

column="civico"></property>

column="cap"></property>

column="citta"></property>

</hibernate-mapping>

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso 2: Uso dei Custom types di Hibernate

2008-2009 Caso 2: Uso dei Custom types di Hibernate Hibernate permette di definire dei tipi Hibernate

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

sono fornite diverse interfacce pi`u o meno complesse a seconda del tipo di conversione da effettuare `e necessario definire una classe Java che implementa una delle interfacce e che effettua la conversione da/verso valori della classe Java che realizza il tipo verso/da valori nella base di dati

l’interfaccia pi`u comunemente usata `e

fornisce i metodi

di base per effettuare il caricamento ed il salvataggio di istanze di classi che realizzano tipi di dato

org.hibernate.usertype.UserType:

Progetto di Applicazioni Software

un’altra interfaccia `e

Anno accademico 2008-2009

org.hibernate.usertype.CompositeUserType:

fornisce inoltre metodi per esporre/modificare propriet`a “interne” di istanze di classi che realizzano tipi UML - non rientra negli scopi del corso

Progetto di Applicazioni Software

Anno accademico 2008-2009

Interfaccia org.hibernate.usertype.UserType

(Esempio)

Interfaccia org.hibernate.usertype.UserType (Esempio) Supponiamo che per le propriet`a giornoInizio e

Supponiamo che per le propriet`a giornoInizio e giornoFine della classe di dominio Item, si decida di evitare l’uso del tipo java.sql.Date e si voglia piuttosto

usare il tipo GregorianCalendar

si deve definire una classe che effettua la conversione dal tipo sql DATE degli attributi inizio e fine della tabella

ITEM al tipo GregorianCalendar

Progetto di Applicazioni Software

Anno accademico 2008-2009

Nel file di mapping Item.hbm.xml si definisce come mappare le propriet`a si cui sopra come segue:

<hibernate-mapping>

<class

name="bid.Item"

table="ITEM">

) (

<property

type="persistence.GregorianCalendarUserType"/>

<property

type="persistence.GregorianCalendarUserType"/>

name="giornoInizio"

column="inizio"

name="giornoFine"

column="fine"

</class>

</hibernate-mapping>

Progetto di Applicazioni Software

Anno accademico 2008-2009

Esempio: classe che implementa un nuovo tipo di Hibernate

Esempio: classe che implementa un nuovo tipo di Hibernate Implementiamo la classe

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

java.io.Serializable;

import

java.sql.PreparedStatement;

import

java.sql.ResultSet;

import

java.sql.SQLException;

import

java.util. * ;

import

org.hibernate. * ;

import

org.hibernate.usertype. * ;

Progetto di Applicazioni Software

Anno accademico 2008-2009

public

class

GregorianCalendarUserType

implements

UserType{

//indica

ad

Hibernate

i

tipi

SQL

da

mappare

-

possono

essere

public

int[]

sqlTypes(){

 

return

new

int[]

{Hibernate.DATE.sqlType()};

 

}

//indica

ad

Hibernate

il

tipo

Java

da

mappare

pi`u

di

uno

public

Class

returnedClass()

 

{

return

GregorianCalendar.class;

 

}

//indica

se

il

tipo

Java

`e

immutabile

 

//utile

per

effettuare

eventuali

ottimizzazioni

 

public

boolean

isMutable()

{

return

false;

 

}

//per

eseguire

il

dirty

checking,

il

tipo

Hibernate

usa

i

seguenti

//metodi,

che

public

boolean

tipicamente

delegano

ai

equals(Object

x,

Object

if

(x==y)

return

true;

if

(x==null

||

y==null)

return

false;

return

x.equals(y);

metodi

corrispondenti

del

tipo

y)

throws

HibernateException

{

Jav

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

//`e

immutabile,

`e

sufficiente

restituire

il

riferimento

all’oggetto

 

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`a

Java

corrispondente

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

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`a

Java

del

//tipo

sul

JDBC

PreparedStatement

che

esegue

il

salvataggio

 

public

void

nullSafeSet(PreparedStatement

statement,

Object

value,

int

i

throws

HibernateException,

SQLException

{

if

statement.setNull(index,Hibernate.DATE.sqlType());

(value==null){

}

else

GregorianCalendar

String

g.get(Calendar.DAY_OF_MONTH);

statement.setDate(index,java.sql.Date.valueOf(s));

{

g=

(GregorianCalendar)

value;

s

=

g.get(Calendar.YEAR)+"-"+g.get(Calendar.MONTH)+"-"+

}

}

//metodo

chiamato

per

effettuare

il

merge

di

ogetti

in

stato

//"detached"

//`e

-

immutabile,

cf.

`e

lezione

pi`u

sufficiente

avanti

-

restituire

se

il

il

tipo

riferimento

all’oggetto

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;

 

}

}

Progetto di Applicazioni Software

Anno accademico 2008-2009

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

che sono valori con molteplicit`a massima diversa da 1 Quando si ha una propriet`a P persistente

Quando si ha una propriet`a P persistente di una classe di dominio D che `e una collezione omogenea (Set,

List,Map

)

di valori gestiti da un’altra tabella TABP, allora

nel file di mapping di D si definisce un elemento apposito

Noi vedremo come mappare Set e List, si rimanda alla doc per gli altri tipi di collezioni omogenee

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare un attributo di tipo Set

Anno accademico 2008-2009 Mappare un attributo di tipo Set Si usa l’elemento set : <set name="P"

Si usa l’elemento set:

<set

name="P"

table="TABP">

<key

<element

column="IDD"/>

type="TypeP"

</set>

column="ColumnP"/>

dove:

IDD `e l’attributo di TABP che identifica l’istanza di D per la quale si definisce il mapping

ColumnP `e la colonna di TABP che contiene i valori della collezione mappati

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare un attributo di tipo List

Anno accademico 2008-2009 Mappare un attributo di tipo List Si usa l’elemento list : <list name="P"

Si usa l’elemento list:

<list

name="P"

table="TABP">

<key

<list-index

<element

column="IDD"/>

column="POSITION"/>

type="TypeP"

column="ColumnP"/>

</list>

dove POSITION `e l’attributo di TABP che contiene il valore dell’indice della lista

Progetto di Applicazioni Software

Anno accademico 2008-2009

Mappare propriet`a che realizzano associazioni

2008-2009 Mappare propriet`a che realizzano associazioni In linea di principio, Hibernate permette di mappare tutte

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

propriet`a riferimento ad un’istanza di un’altra classe persistente

propriet`a insieme di riferimenti ad istanze di un’altra classe

propriet`a riferimento ad un’istanza di una classe “TipoLink”

propriet`a insieme di riferimenti ad istanze di una classe “TipoLink”

Progetto di Applicazioni Software

Anno accademico 2008-2009

Propriet`a riferimento ad un’istanza di un’altra classe persistente

riferimento ad un’istanza di un’altra classe persistente Consideriamo il caso di due classi di dominio A

Consideriamo il caso di due classi di dominio A e B

persistenti legate da un’associazione R senza attributi, con

molteplicit`a 0

la realizzazione in Java della classe A porta ad una propriet`a P ropB che `e un riferimento ad un’istanza della classe B.

Indichiamo con TabA e TabB rispettivamente le tabelle su cui sono mappate A e B.

1

o 1

1,

sulla quale solo A ha responsabilit`a

Progetto di Applicazioni Software

Ci sono 2 casi:

Anno accademico 2008-2009

Caso 1: TabA ha accorpato la relazione ER corrispondente a R in TabA sar`a definito un vincolo di foreign key verso

TabB

Si usa l’elemento one-to-one:

<one-to-one

name="PropB"

class="B"/>

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 l’elemento join:

<join

table="TabR">

<key

<many-to-one

column="FKA"/>

name="PropB"

</join>

class="B"

column="FKB"/>

Progetto di Applicazioni Software

Anno accademico 2008-2009

Propriet`a insieme di riferimenti ad istanze di un’altra classe persistente

di riferimenti ad istanze di un’altra classe persistente Consideriamo il caso di due classi di dominio

Consideriamo il caso di due classi di dominio A e B persistenti legate da un’associazione R senza attributi, con

molteplicit`a 0

o 1

sulla quale solo A ha responsabilit`a

,

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 `e definita una foreign key FKA verso TabA

Si usa l’elemento set:

<set

table="TabB"

optional="true">

<key

<one-to-many

column="FKA"/>

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 `e contenuta nella chiave nella

chiave primaria di TabA, allora Hibernate permette ad

implementare il mapping

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 l’elemento join:

<join

table="TabR"

optional="true">

<key

<many-to-one

column="FKA"/>

name="PropB"

</join>

class="B"

column="FKB"/>

Progetto di Applicazioni Software

Anno accademico 2008-2009

Cascading di oggetti

Software Anno accademico 2008-2009 Cascading di oggetti Quando una classe A ha responsabilit`a su di

Quando una classe A ha responsabilit`a su di un’associazione AB con B, Hibernate fornisce la possibilit`a di richiedere che una qualsiasi operazione di persistenza su A sia transitiva es. il salvataggio di un oggetto di A, implichi il salvataggio dell’oggetto di B associato ad A

Si definisce uguale ad "all" l’attributo cascade dell’elemento XML che definisce il mapping per l’associazione per indicare ad Hibernate che tutte le operazioni devono essere persistenti (altrimenti si usa il nome dell’operazione, 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)

Progetto di Applicazioni Software

Anno accademico 2008-2009

Caso in cui si ha una classe di tipo “TipoLink”

Caso in cui si ha una classe di tipo “TipoLink” Siano A e B due classi