• Non ci sono risultati.

Università degli Studi di Padova Dipartimento di Ingegneria dell’Informazione Corso di Laurea Triennale in Ingegneria Informatica Studio di Hibernate attraverso i costrutti del modello relazionale

N/A
N/A
Protected

Academic year: 2021

Condividi "Università degli Studi di Padova Dipartimento di Ingegneria dell’Informazione Corso di Laurea Triennale in Ingegneria Informatica Studio di Hibernate attraverso i costrutti del modello relazionale"

Copied!
47
0
0

Testo completo

(1)

Università degli Studi di Padova

Dipartimento di Ingegneria dell’Informazione

Corso di Laurea Triennale in Ingegneria Informatica

Studio di Hibernate attraverso i costrutti del

modello relazionale

Laureando Relatore

Marco Carraro Prof. Giorgio Maria Di Nunzio

(2)
(3)

Alla mia famiglia e a Silvia ringraziandovi per il vostro sostegno, la vostra pazienza e la vostra comprensione

(4)
(5)

INDICE

Indice

1 Introduzione 7 1.1 Obiettivi . . . 8 1.2 Strumenti Utilizzati . . . 9 1.2.1 Eclipse . . . 9 1.2.2 PostgreSQL . . . 9 1.2.3 OmniGraffle . . . 9 1.2.4 PhpPgAdmin . . . 9

2 Modello Concettuale e Modello Relazionale 11 2.1 Modello Concettuale . . . 11

2.2 Modello Relazionale . . . 12

3 Implementazione di Schemi Relazionali con Hibernate 15 3.1 Configurazione di Hibernate . . . 15

3.1.1 Package e directory . . . 15

3.1.2 hibernate.cfg.xml . . . 15

3.1.3 Package Persistence . . . 18

3.1.4 Librerie . . . 18

3.2 Classi e Files di Mappatura . . . 19

3.3 Associazioni Binarie Uno a Uno . . . 20

3.3.1 Associazione Uno ad Uno con Entità Debole . . . 21

3.3.2 Associazione Uno Ad Uno con Entità Debole e Partecipazione Par-ziale Dell’Entità Forte . . . 23

3.3.3 Associazione Uno Ad Uno con Partecipazione Facoltativa Di Un’Entità 26 3.4 Associazioni Binarie Uno a Molti . . . 27

3.4.1 Associazione Uno a Molti Con Liste, Bags, Sets . . . 27

3.4.2 Associazione Uno a Molti Con Partecipazioni Opzionali . . . 31

3.4.3 Associazione Uno a Molti Con Attributo sull’Associazione . . . 32

3.5 Associazioni Binarie Molti a Molti . . . 36

3.5.1 Associazioni Molti a Molti Semplici . . . 36

3.5.2 Associazioni Molti a Molti con Attributi Comuni . . . 38

3.6 Associazioni Ternarie . . . 40

4 Conclusioni 45

(6)
(7)

1

Introduzione

Ogni programmatore prima o poi nella sua vita incontra il problema di come rendere per-sistenti gli oggetti che usa nelle sue applicazioni, ovvero come far sopravvivere tali oggetti anche dopo la fine di un’applicazione. Un primo metodo che risolve questo problema è quello di utilizzare dei file, manovra che però porta via moltissimo tempo nella scrittura di classi e metodi ad hoc per ogni applicazione e che non fornisce un controllo degli accessi concorrenti. Tale metodo è quindi poco usato anche se rimane una buona soluzione per necessità di pochi dati persistenti utilizzati da un’unica persona.

Un metodo alternativo consiste l’utilizzo di sistemi di gestione di basi di dati che consen-tono di accelerare il lavoro dei programmatori fornendo la possibilità di gestire l’accesso multiplo ai dati, controllando la ridondanza nei dati, introducendo meccanismi di backup and restore e molti altri vantaggi.

Nel linguaggio Java per accedere ai database bisogna ricorrere alle connessioni JDBC1 (Ja-va DataBase Connectivity) che fungono da collegamento tra applicazione e base di dati. Uno studio fatto recentemente tra i programmatori Java sottolinea come il setting dei da-tabase attraverso connessioni JDBC occupi mediamente un terzo del tempo totale per lo sviluppo di un’applicazione (tra scrittura del codice e mantenimento delle connessioni). Per ovviare a questo problema sono nati gli ORM (Object Relational Mapping)2 che sono delle tecniche di programmazione che forniscono interfacce per trasformare dati da modello relazionale a modello ad oggetti e viceversa. Tali applicazioni consentono al programma-tore un elevato riutilizzo del codice e permettono di snellire enormemente la procedura per rendere gli oggetti persistenti.

Hibernate3 è un’implementazione open source degli ORM. L’obiettivo primario dei suoi sviluppatori è quello di semplificare il processo di persistenza degli oggetti, rendendo tra-sparente l’accesso ai DBMS4(DataBase Management System) e nascondendo il particolare tipo di implementazione utilizzato.

Hibernate riesce a soddisfare tale obiettivo introducendo i seguenti vantaggi:

• Produttività: Il codice relativo alla persistenza degli oggetti può essere la parte più tediosa di un’applicazione. Hibernate elimina gran parte del codice necessario per rendere persistenti gli oggetti. Questo per ogni tipo di strategia: analizzando un problema e creando il database relativo o partendo da un database esistente. • Mantenimento: Scrivere meno righe di codice rende un’applicazione più comprensibile

(8)

1 INTRODUZIONE

parte o dall’altra le operazioni da effettuare sono ben definite e limitate in modo da migliorare il mantenimento dell’applicazione.

• Controllo migliore delle performance: Hibernate introduce anche delle tecniche che permettono di controllare le performance di un’applicazione ottimizzando al massimo le interazioni con il/i database utilizzati nell’applicazione creata.

• Indipendenza da architetture/prodotti: Hibernate riesce ad astrarre l’applicazione rispetto al DataBase Management System utilizzato e al dialetto SQL utilizzato. Questo permette di spostare l’applicazione su altre macchine che utilizzano diversi DBMS mantenendone il funzionamento.

1.1 Obiettivi

Hibernate è un progetto nato diversi anni fa che è molto diffuso tra gli sviluppatori. Per questo c’è un’ampia letteratura che riguarda il mondo degli ORM e che si pone l’obiettivo di semplificare la vita ai programmatori che si avvicinano a questo mondo.

Poichè Hibernate si pone a metà tra il mondo dei database e la programmazione ad oggetti per comprenderne tutte le sfaccettature è necessario capire tutti e due i mondi. Uno dei maggiori problemi riguardante la letteratura dell’argomento è che le spiegazioni e la documentazione presente è quasi interamente dedicata ad un esperto programmatore Java che deve rendere persistenti i suoi oggetti.

Non c’è, o comunque è imprecisa, della letteratura che analizzi Hibernate dal punto di vista del modello relazionale e di come implementare efficacemente in Hibernate situazioni descritte molto bene da uno schema relazionale.

L’obiettivo di questa tesi è quello quindi di fornire della documentazione su come far funzionare Hibernate a partire da problemi modellizzati con uno o più schemi relazionali. La trattazione che verrà seguita sarà quindi la seguente:

1. Analizzare problemi reali (verranno ripresi esempi a partire dal sito di aste online presente nel libro in bibliografia alla voce [1]);

2. Ricavare schemi Entity-Relationship secondo lo standard del libro in bibliografia alla voce [2];

3. Mostrare possibili traduzioni in schemi relazionali (a volte più di una possibile tra-duzione);

4. Fornirne l’implementazione con Hibernate.

(9)

1.2 Strumenti Utilizzati

possibile collegarsi a:

http://www.dei.unipd.it/~carraro1

1.2 Strumenti Utilizzati

1.2.1 Eclipse

Eclipse5 è un IDE(Integrated Development Environment) ovvero un ambiente di sviluppo multi-linguaggio e multi-piattaforma open-source. E’ stata utilizzata la versione Indigo per la realizzazione degli esempi Java con Hibernate.

1.2.2 PostgreSQL

PostgreSQL6 è un completo database relazionale open-source. E’ stato utilizzato negli esempi sebbene come già detto nei precedenti paragrafi la scelta di un DBMS non sia vincolante per il funzionamento dell’applicazione. Ho utilizzato questo DBMS per coerenza con i corsi che ho frequentato in questo corso di laurea.

1.2.3 OmniGraffle

OmniGraffle7 è un software di disegno che gira su ambiente Mac. Permette di disegnare flow-chart, Diagrammi Entity-Relationship e numerosi altri tipi di grafici e diagrammi. E’ stato utilizzato per creare le varie figure presenti nella tesi.

1.2.4 PhpPgAdmin

PhpPgAdmin8 è un’applicazione PHP libera che consente di amministrare in modo sem-plificato database di PostgreSQL tramite un qualsiasi browser. E’ stato utilizzato per verificare i risultati delle varie classi di Test dei vari esempi e per la produzione delle immagini dei risultati.

(10)
(11)

2

Modello Concettuale e Modello Relazionale

In questa tesi si farà più volte riferimento al modello concettuale ed al modello relazionale. In questo capitolo verranno dati i fondamenti teorici riguardanti i due modelli per poter meglio comprendere di cosa si sta parlando.

2.1 Modello Concettuale

La modellazione concettuale è una fase molto importante nella progettazione di una buona base di dati. Infatti solitamente la progettazione si articola nei seguenti passaggi:

1. Raccolta ed analisi dei requisiti attraverso interviste al committente; 2. Progettazione concettuale;

3. Progettazione logica; 4. Progettazione fisica.

Dalla lista precedente si può capire come la progettazione concettuale sia un passo fonda-mentale per arrivare ad una buona base di dati. In questa tesi per i vari esempi si partirà direttamente da uno schema concettuale già fatto, si tradurrà in schema relazionale (pro-gettazione logica) e si implementeranno con Hibernate i vari schemi trovati.

Il modello concettuale utilizzato sarà il modello Entity Relationship9, che è un modello ad alto livello di astrazione formalizzato da Peter Chen10. Poichè non esiste uno standard per tale diagramma verrà utilizzato quello adottato nel corso di Basi Di Dati frequentato nel terzo anno della laurea triennale di Ingegneria Informatica a Padova. Tale standard è quello usato nel libro in bibliografia alla voce [2].

Il modello Entity-Relationship si basa su tre definizioni ovvero:

• Entità: Un’entità rappresenta una classe di oggetti che ha caratteristiche comuni ai fini dell’applicazione di interesse. In ogni schema entity relationship l’entità viene indicata con un rettangolo con all’interno il suo nome univoco;

• Associazione: Un’associazione rappresenta un legame esistente tra due o più entità. Il numero di entità collegate dall’associazione è chiamato grado dell’associazione. In questa tesi sono presenti solo associazioni binarie e ternarie in quanto le altre sono spesso traducibili come combinazioni di queste. L’associazione viene indicata con un rombo con all’interno il suo nome;

9

http://it.wikipedia.org/wiki/Modello_E-R

(12)

2 MODELLO CONCETTUALE E MODELLO RELAZIONALE

• Attributo: Le entità e le associazioni sono descritte da una serie di attributi che esprimono delle caratteristiche e dell’informazione riguardante un’entità o un’asso-ciazione. Gli attributi vengono indicati con un pallino collegato all’entità o all’asso-ciazione a cui appartengono. Il pallino può essere vuoto se indica un attributo con valori che possono ripetersi tra un’istanza ed un’altra dell’associazione o dell’entità oppure pieni.

In figura 1 è presente un’esempio di schema Entity-Relationship dove X e W possono es-sere o 0 o 1 anche diversi tra loro mentre Y e Z possono assumere 1 o N dove N assume il significato di molti.

Figura 1: Esempio di schema E-R

2.2 Modello Relazionale

Il modello relazionale fu introdotto da Codd11 della IBM nel 1970. Ebbe molto successo in quanto molto semplice grazie al fatto che usava i concetti matematici di insieme e della logica del primo ordine.

Il modello relazionale presenta la base di dati come una collezione di relazioni basandosi quindi sulla definizione di relazione matematica, formata da stato della relazione e schema di relazione.

Prima di introdurre tali concetti è opportuno introdurre i seguenti:

• Dominio: Un dominio D è un insieme di valori atomici. Per atomici si intende che ogni valore nel dominio è indivisibile, per lo meno per quanto riguarda il modello relazionale.

• Attributo: Un attributo Aifornisce il nome del ruolo interpretato da un certo dominio D.

(13)

2.2 Modello Relazionale

Di seguito i concetti di schema di relazione e stato della relazione:

• Uno schema di relazione R, indicato con R(A1, A2, ..., An), è costituito da un nome di relazione R e da un elenco di attributi A1, A2, ..., An. Ogni attributo Ai come già detto è il nome del ruolo interpretato da un certo dominio D nello schema di relazione R. Tale D è detto dominio di Ai.

Uno schema di relazione è usato per descrivere una relazione; R è detto nome della relazione, mentre il grado della relazione è n ovvero il numero di attributi che ne fanno parte.

• Uno stato di relazione r dello schema di relazione R(A1, A2, ..., An), indicato anche con r(R), è un insieme di n-tuple r = {t1, t2, ..., tn}. Ogni n-tupla t è un elenco ordinato di n valori t =< v1, v2, ..., vn> dove ogni valore vi, 1 ≤ i ≤ n è un elemento del dominio di Ai oppure è uno speciale valore null.

Il concetto di relazione è rappresentabile efficacemente mediante una tabella. Quest’ultima però rappresenta un concetto differente rispetto a quello di relazione. In una relazione infatti non è presente il concetto di ordine tra le tuple al suo interno cosa che mediante rappresentazione tabellare si introduce. Infatti in generale una relazione è un insieme di Rn mentre una tabella è una rappresentazione piatta di tale insieme.

Nelle relazioni in una base di dati è possibile anche introdurre dei vincoli, alcuni dei quali già introdotti tramite la definizione di una relazione. Di seguito sono elencati questi vincoli: • Vincoli di dominio: Questo tipo di vincolo impone che all’interno di ciascuna tupla il valore di ogni attributo A deve essere un valore atomico del suo dominio D o al massimo un valore speciale null.

• Vincoli di chiave: Una relazione come già detto è formata da un insieme di tuple. Poichè si parla di insieme non sono ammessi valori duplicati al suo interno, quindi le tuple devono essere differenti tra loro. Tali differenze sono visibili osservando un sottoinsieme di attributi SK di uno schema di relazione R che hanno la proprietà che prese due tuple distinte ti, tj ⇒ ti[SK] 6= tj[SK]. Tali sottoinsiemi che soddisfano questa proprietà sono detti superchiavi di R.

(14)
(15)

3

Implementazione di Schemi Relazionali con Hibernate

In questa sezione si fornirà della documentazione per mappare correttamente con Hibernate situazioni possibili di schemi relazionali possibili nella modellazione di un database. Per ogni esempio si cercheranno di dare tutte le possibili traduzioni in schema relazionale possibili.

3.1 Configurazione di Hibernate

In questo paragrafo verrà mostrata la configurazione di Hibernate utilizzata per far fun-zionare correttamente tutti gli esempi illustrati in seguito. Come già descritto nell’In-troduzione, uno dei vantaggi introdotti da Hibernate è il largo riutilizzo del codice da un’applicazione all’altra, per questo affinchè vi siano meno ripetizioni possibili nei para-grafi seguenti verranno omesse delle classi e dei file di configurazione identici o molto simili tra i vari esempi. Tali configurazioni e classi verranno mostrati quindi una sola volta.

3.1.1 Package e directory

Tutti gli esempi sono stati testati con i package e le directory presenti nella seguente figura:

Figura 2: Package And Directory

La cartella src contiene tutto il codice relativo al progetto (classi e file .xml), in particolare contiene due ulteriori package ovvero entity e persistence più un file di configurazione hibernate.cfg.xml che verrà spiegato in dettaglio nei prossimi paragrafi. La cartella lib contiene tutte le librerie necessarie al corretto funzionamento di Hibernate, tali librerie devono venire correttamente importate da Eclipse alla creazione del progetto nuovo (non basta metterle dentro la cartella lib). Il package entity è quello che contiene tutte le classi e i file xml relativi ad ogni esempio, mentre il package persistence contiene al suo interno la classe HibernateUtil.java. Tutto il codice da qui in avanti si rifarà a tale organizzazione.

3.1.2 hibernate.cfg.xml

(16)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Figura 3: Hibernate e Connection Pool

a partire dalle configurazioni date, che servirà per poter usare le sessioni ovvero gli oggetti che serviranno a colloquiare con il database. Nel listato 1 si mostra quello utilizzato per gli esempi in questa tesi. Il DTD usato (righe da 2 a 4) serve per dare possibilità al parser XML di validare il file.

Le righe da 7 a 21 danno ad Hibernate le informazioni necessarie perchè conosca il DBMS utilizzato nel sistema corrente, queste sono le uniche righe da modificare in caso di cambio di DBMS (anche in presenza di applicazioni complicate si modificano solo poche righe di codice e tutto può girare anche su sistemi con DBMS diversi).

Le righe da 23 a 31 servono a settare il Database Connection Pool che è un insieme di connessioni mantenute in cache per minimizzare il costo dell’apertura e della chiusura di queste e velocizzare le performance delle interazioni con un database. Per questa tesi è stato usato c3p012 che è un Database Connection Pool open-source facilmente reperibile. In figura 3 è schematizzato l’ambiente Java con Hibernate e il Connection Pool.

Le righe relative al connection pool sono opzionali ma ci sono tre buoni motivi per utiliz-zarle:

• Acquisire una nuova connessione è costoso. Inoltre alcuni DBMS fanno partire un nuovo processo server per ogni connessione;

• Mantenere connessioni idle è costoso per i DBMS e il pool ne ottimizza l’uso; • Il pool fornisce un meccanismo di caching che permette di immagazzinare query

(17)

3.1 Configurazione di Hibernate

(18)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Modificando quindi le righe di codice relative al pool è possibile agire direttamente sulle performance di un’applicazione che usa Hibernate. Ecco la spiegazione relativa ai campi del Database Connection Pool:

• La riga 23 fornisce la quantità minima di connessioni tenute pronte dal connection pool, mentre la riga 24 da il numero massimo di connessioni nel pool.

• La riga 25 fornisce il tempo massimo dopo il quale una connessione idle viene rimossa dal pool

• Le righe 26-28 danno il numero massimo di prepared statements che possono essere in cache. Questo campo è molto importante per le performance di Hibernate. Infine per poter usare c3p0 è necessario aggiungere le librerie necessarie al suo funziona-mento (verranno spiegate nella sezione 3.1.4).

La riga 30 è molto importante a livello di debug, infatti la proprietà hbm.dll.auto dice ad Hibernate cosa fare sul database sul quale si lavora. In questo caso la proprietà è setta-ta su create, in questo modo Hibernate provvede a rimuovere lo schema presente appena l’applicazione si avvia e lo rimpiazza con quello nuovo generato dall’applicazione. In poche parole con questa impostazione si perderebbero tutti i dati immagazzinati sul database ad ogni riavvio dell’applicazione. Ovviamente ciò non è quello che si vuole normalmente ma in fase di creazione del database questa proprietà è utile. Una volta che si è verificata la bontà dell’applicazione creata la riga va commentata o tolta.

Infine la righe da 32 a 33 forniscono un’indicazione di dove si trovano i file di mappatu-ra necessari per far capire ad Hibernate la struttumappatu-ra delle classi e come dialogare con il database. Tali file di mappatura sono differenti da esempio ad esempio e vanno sempre specificati sempre tutti in queste righe.

3.1.3 Package Persistence

Il package persistence contiene al suo interno un’unica classe ovvero HibernateUtil.java. Tale classe indicata nel listato 2 serve per creare correttamente la SessionFactory a partire dal file di configurazione hibernate.cfg.xml. Poichè tali operazioni sono comuni a tutti gli esempi si è scelto di creare tale classe per poi importarla nelle classi di Test degli esempi per rendere meglio visibile il codice.

3.1.4 Librerie

(19)

3.2 Classi e Files di Mappatura Listing 2: HibernateUtil.java 1 p a c k a g e p e r s i s t e n c e ; 2 i m p o r t org . h i b e r n a t e .*; 3 i m p o r t org . h i b e r n a t e . cfg .*; 4 p u b l i c c l a s s H i b e r n a t e U t i l { 5 p r i v a t e s t a t i c S e s s i o n F a c t o r y s e s s i o n F a c t o r y ; 6 s t a t i c{ 7 try{ 8 s e s s i o n F a c t o r y =new C o n f i g u r a t i o n (). c o n f i g u r e (). 9 b u i l d S e s s i o n F a c t o r y (); 10 }c a t c h( T h r o w a b l e ex ){ 11 t h r o w new E x c e p t i o n I n I n i t i a l i z e r E r r o r ( ex ); 12 } 13 } 14 p u b l i c s t a t i c S e s s i o n F a c t o r y g e t S e s s i o n F a c t o r y (){ 15 r e t u r n s e s s i o n F a c t o r y ; 16 } 17 p u b l i c s t a t i c v o i d s h u t d o w n (){ 18 g e t S e s s i o n F a c t o r y (). c l o s e (); 19 } 20 }

• Librerie associate al core di Hibernate13 • Libreria associata al DBMS14

• Libreria di c3p015

3.2 Classi e Files di Mappatura

Per poter correttamente costruire un ponte tra il mondo database e il mondo Java, Hiber-nate ha bisogno di conoscere le informazioni relative all’applicazione come gli attributi che verranno utilizzati nelle classi e che relazioni si intende ottenere. Tali informazioni vengono prelevate da dei file di mappatura scritti in XML che si accompagnano alle varie classi. In tali file sono presenti informazioni sugli attributi e soprattutto sui vincoli tra una classe e l’altra dalle quali Hibernate potrà tradurre correttamente i vincoli nel mondo relazionale.

13

Le librerie sono scaricabili da

http://sourceforge.net/projects/Hibernate/files/latest/download?source=files

al percorso dist/lib/required 14

Per PostgreSQL tale file è postgresql-9.1-901.jdbc4.jar scaricabile da

http://jdbc.postgresql.org/download/postgresql-9.1-902.jdbc4.jar

15

Il file si chiama c3p0.jar ed è scaricabile da

(20)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Listing 3: Formato file di mappatura XML 1 < ?xml v e r s i o n=" 1.0 " e n c o d i n g =" UTF -8 "? > 2 < !D O C T Y P E h i b e r n a t e - m a p p i n g P U B L I C 3 " -// H i b e r n a t e / H i b e r n a t e M a p p i n g DTD 3 . 0 / / EN " 4 " h t t p : // www . h i b e r n a t e . org / dtd / h i b e r n a t e - mapping - 3 . 0 . dtd "> 5 < h i b e r n a t e - m a p p i n g > 6 < c l a s s na m e =" p a c k a g e . C l a s s N a m e " t a b l e =" T a b l e N a m e "> 7 < id n a m e =" I d N a m e " c o l u m n =" I D _ C O L U M N _ N A M E "> 8 < g e n e r a t o r c l a s s =" C L A S S "> 9 ... 10 < / g e n e r a t o r > 11 < / id > 12 < p r o p e r t y n a m e =" via " c o l u m n =" VIA "/ > 13 ... 14 < / c l a s s > 15 < / h i b e r n a t e - m a p p i n g >

Un file di mappatura XML ha la struttura mostrata nel listato 3. Come si può vedere dunque ogni attributo che non abbia un vincolo di integrità referenziale viene mappato tramite un’unica riga mentre attributi che riferiscono a campi di relazioni diverse saranno mappate attraverso diversi tag come si vedrà nei prossimi esempi.

3.3 Associazioni Binarie Uno a Uno

Per associazione binaria uno ad uno si intende un’associazione che coinvolge due entità con cardinalità (0,1) o (1,1) da entrambi i lati dell’associazione. Ciò implica che un’istanza di un’entità può essere collegata tramite l’associazione al massimo ad un’istanza dell’altra entità. A seconda che la cardinalità minima sia 0 o 1 la traduzione possibile in schema relazionale può variare. Se la cardinalità è (1,1) ambo i lati siamo in una situazione di questo tipo:

(21)

3.3 Associazioni Binarie Uno a Uno

A(A11,A12,R11,B12)

Ciò è dovuto al fatto che A11 e B11 assumono gli stessi valori e normalmente l’entità A e l’entità B non rappresentano concetti molto differenti tra loro. Tale soluzione verrà ripresa nei prossimi esempi di associazioni uno ad uno con particolarità quali entità deboli o partecipazioni parziali di alcune entità all’associazione.

3.3.1 Associazione Uno ad Uno con Entità Debole

Consideriamo una base di dati che raccoglie gli utenti di un sito web. Ognuno di questi utenti deve avere un solo indirizzo e gli indirizzi di due utenti qualsiasi nella base di dati devono essere diversi, non può quindi capitare che due utenti condividano lo stesso indirizzo. Lo schema concettuale che descrive il problema è il seguente:

Figura 5: Modello Entity-Relationship Address e User Ci sono due possibili schemi relazionali ottenibili mediante traduzione ovvero:

Figura 6: Schemi Relazionali Possibili

Normalmente il primo caso è preferibile al secondo in quanto si hanno meno relazioni, ma per completezza verranno illustrate entrambe le mappature anche perchè la scelta va fatta valutando volume dei dati e query più frequenti.

(22)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE Listing 4: User.java 1 p a c k a g e e n t i t y ; 2 3 p u b l i c c l a s s U s e r { 4 p r i v a t e L o n g id ; 5 p r i v a t e S t r i n g l o g i n ; 6 p r i v a t e A d d r e s s a d d r e s s ; 7 8 p u b l i c U se r ( ) { } 9 10 p u b l i c U se r ( S t r i n g u s e r ){ 11 l o g i n = u s e r ; 12 } 13 p u b l i c U se r ( S t r i n g user , A d d r e s s a d d r e s s ){ 14 l o g i n = u s e r ; 15 t h i s. a d d r e s s = a d d r e s s ; 16 } 17 // g e t t e r and s e t t e r 18 }

per i prossimi non saranno mostrate. A seconda che la traduzione scelta sia la prima o la seconda bisogna accompagnare le classi Java a delle determinate mappature in XML, di seguito si analizzano tutti e due i casi:

• Accorpamento in un’unica entità: E’ necessario utilizzare un unico file XML di mappatura che si occuperà di creare l’unica relazione presente nello schema relazio-nale. Gli attributi accorpati ovvero Street, PostalCode e City vengono riconosciuti attraverso l’utilizzo del tag <component> che richiama una classe esterna rispetto a quella che si sta mappando. Nel listato 6 è presente il file di mappatura per User. Tale file va salvato assieme alle classi Java nel package entity ed è sufficiente per la corretta creazione/interazione con il modello relazionale di fig 6 caso 1)

• Due Relazioni Distinte: Se la traduzione scelta è quella di tradurre lo schema in due relazioni distinte allora è necessario modificare il file XML User.hbm.xml ed aggiungere anche un file di mappatura Address.hbm.xml per la relazione Address. Un’altra modifica da fare è rendere Address una Entity type. I concetti di Entity Type e Value Type sono molto importanti in Hibernate, il primo indica una classe con un identificatore univoco mentre il secondo rappresenta una classe senza identificatore e che viene identificata esternamente. Tale concetto ricorda molto quello di entità debole ed entità forte.

(23)

3.3 Associazioni Binarie Uno a Uno

Type. Per rendere bidirezionale l’associazione inoltre bisogna aggiungere anche un attributo di tipo User ad Address chiamato address. I listati 7 e 8 mostrano i file di mappatura. Come si può notare gli identificatori della tabella relativa ad Address sono chiavi esterne verso gli identificatori della tabella relativa ad User. Ciò si ottiene attraverso il tag <generator> con attributo class=foreign che richiede di specificare a che parametro rifarsi per la generazione degli identificatori. In questo caso tutto funziona perchè è presente il tag <one-to-one> alla fine del file Address.hbm.xml che collega user (l’oggetto di tipo User nella classe Address) alla classe User. L’attributo constrained=true è necessario perchè venga creata correttamente la chiave esterna alla tabella relativa ad User.

3.3.2 Associazione Uno Ad Uno con Entità Debole e Partecipazione Parziale

Dell’Entità Forte

Riprendendo l’esempio della sezione precedente supponiamo che non sia obbligatorio che ogni utente indichi il proprio indirizzo (che rimane comunque al massimo uno). Questa piccola differenza si riflette nella cardinalità minima di User che diventa 0 come mostrato nello schema Entity-Relationship di figura 7. Anche in questo caso verranno utilizzate le

Figura 7: Schema Entity-Relationship User-Address con partecipazione facoltativa di User stesse classi già mostrate nei listati relativi ad User ed Address. La traduzioni in schema relazionale possibili sono analoghe a quelle indicate precedentemente (fig. 6), in questa situazione però il caso 1) andrebbe scelto solo se si fosse sicuri che la maggior parte degli utenti indichi il proprio indirizzo altrimenti si rischierebbe di sprecare molto spazio per valori nulli.

(24)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE Listing 5: Address.java 1 p a c k a g e e n t i t y ; 2 3 p u b l i c c l a s s A d d r e s s { 4 p r i v a t e S t r i n g s t r e e t ; 5 p r i v a t e int num ; 6 p r i v a t e int cap ; 7 8 p u b l i c A d d r e s s ( ) { }

(25)
(26)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE Listing 9: Address2.hbm.xml 1 ... 2 < id n a m e =" id " c o l u m n =" A D D R E S S _ I D "> 3 < g e n e r a t o r c l a s s =" f o r e i g n "> 4 < p a r a m n a m e =" p r o p e r t y "> u s e r < / p a r a m > 5 < / g e n e r a t o r > 6 < / id > 7 ...

oggetto User non appena si tenta di rendere persistente l’oggetto Address viene lanciata un’eccezione da Hibernate.

3.3.3 Associazione Uno Ad Uno con Partecipazione Facoltativa Di Un’Entità

Consideriamo sempre lo stesso esempio che coinvolge User e Address. In questo caso però abbiamo dei vincoli che ci impongono che uno User può avere oppure no un indirizzo (e se lo ha ne ha uno e uno solo) e ogni Address è associato ad uno e un solo User. La situazione può essere schematizzata dal seguente schema E-R:

Figura 8: Modello Entity-Relationship sezione 3.3.3

Le classi Java necessarie per la mappatura sono sempre User.java e Address.java con l’ecce-zione che ora Address necessita di un’attributo di tipo long chiamato id che rappresenterà l’identificatore di Address. Anche per questo caso sono possibili traduzioni analoghe a quelle fatte in precedenza, e se si sceglieranno tali traduzioni le modifiche da effettuare ai casi precedenti sono poche. Analizziamo invece la seguente traduzione:

(27)

3.4 Associazioni Binarie Uno a Molti

Listing 10: Frammento User.hbm.xml

1 ... 2 < j o i n t a b l e =" L I V E " o p t i o n a l =" t r u e "> 3 < key c o l u m n =" U S E R _ I D "/ > 4 < many - to - one n a m e =" a d d r e s s " c o l u m n =" A D D R E S S _ I D " 5 not - n u l l =" tr u e " u n i q u e =" t r u e " c a s c a d e =" save - u p d a t e "/ > 6 < / j o i n > 7 ...

In questo caso dobbiamo generare una relazione centrale che manterrà i collegamenti tra una relazione e l’altra attraverso dei vincoli di integrità referenziali. Tale scelta è ottenibile mediante i soliti due file di mappatura, uno per User e l’altro per Address, denominati User.hbm.xml e Address.hbm.xml. Quest’ultimo non verrà mostrato in quanto non rap-presenta nessuna particolarità, l’unica differenza rispetto ai casi precedenti è che la classe Address è diventata un’Entity Type vera e propria con il proprio identificatore di tipo long. Pertanto nel campo id andrà specificato un <generator class=identity/> come per User.hbm.xml.

E’ invece interessante notare come si ottenga la relazione centrale LIVE incorporando nel file User.hbm.xml il codice nel listato 10. Si può notare quindi come attraverso il tag <join table> sia possibile definire dei vincoli di integrità referenziali tra entità su una relazione differente. Tale scelta è comoda soprattutto in caso di opzionalità da ambo i lati nell’ associazione per evitare scomodi valori nulli nelle due relazioni.

3.4 Associazioni Binarie Uno a Molti

Per associazione binaria uno a molti si intende un’associazione che coinvolge due entità con cardinalità (1,1) o (0,1) da un lato dell’associazione e cardinalità (1,N) o (0,N) dall’altro. Anche in questo caso a seconda che la cardinalità minima sia zero da una o tutte due le parti può far pendere la traduzione in modello relazionale verso una soluzione invece di un’altra. Nei prossimi paragrafi verranno descritte le soluzioni più comuni.

3.4.1 Associazione Uno a Molti Con Liste, Bags, Sets

Quando ci si trova davanti ad una situazione di questo tipo in un programma Java normal-mente si hanno due classi una delle quali al suo interno ha come attributo una collezione di oggetti dell’altra classe (questa classe rappresenta l’entità coinvolta nell’associazione con cardinalità (0,N) o (1,N)). C’è quindi bisogno di un oggetto collezione che sia riconosciuto correttamente da Hibernate, così che si creino i corretti vincoli di integrità referenziale tra le relazioni coinvolte.

(28)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

classi contenute nel package java.util, in questa tesi verranno analizzate le tre collezioni più utilizzate ovvero Set, Bag e List. Le tre collezioni differiscono per le politiche di gestione degli elementi al loro interno in particolare:

1. Set: Un Set è un insieme di elementi non ordinati in cui i duplicati non sono ammessi. E’ la scelta più comune con Hibernate e quella di cui è presente la maggior documen-tazione in rete. Un Set normalmente soddisfa tutte le necessità di una applicazione che debba interagire con database. In Java un Set si implementa utilizzando la classe java.util.HashSet. In questa tesi eccetto questa sezione in cui verranno esemplifica-ti tutesemplifica-ti e tre i esemplifica-tipi di collezione si userà un Set ogni qual volta ci sarà bisogno di una collezione (ovvero quando avremo una entità coinvolta in una associazione con cardinalità massima N).

2. Bag: Un Bag è una collezione di elementi non ordinati in cui sono ammessi i duplicati. In Java non esiste una classe che implementi un Bag nei package standard ma è possibile servirsi di java.util.Collection e java.util.ArrayList per realizzarne uno. 3. List: Un List è una struttura dati di tipo FIFO (First In First Out) e in Java si

realizza tramite la classe java.util.ArrayList

Per vedere le differenze tra le mappature utilizzando i tre tipi di collezione analizziamo la seguente situazione:

Consideriamo una base di dati relativa ad un sito di aste online. Tale sito vende degli oggetti (ITEM) all’utente che fa l’offerta (BID) migliore. Per un ITEM possono esserci più offerte ma ogni offerta è relativa ad un unico oggetto. La base di dati deve tenere in memoria tutte le offerte e tutti gli item trattati nel sito.

Lo schema E-R che descrive la situazione è visualizzato in figura 10. Si potrebbe anche

Figura 10: Schema E-R tra ITEM e BID

pensare all’entità ITEM come entità debole ma questo cambierebbe poco dal punto di vista della mappatura con Hibernate (cambierebbe il tag <generator> come si vede nel listato 8).

(29)

3.4 Associazioni Binarie Uno a Molti Listing 11: Bid.java 1 p a c k a g e e n t i t y ; 2 p u b l i c c l a s s Bid { 3 p r i v a t e l o n g id ; 4 p r i v a t e d o u b l e a m o u n t ; 5 p r i v a t e I t e m i t e m ; 6 ... 7 // c o n s t r u c t o r s , s e t t e r and g e t t e r 8 } Listing 12: Item.java 1 p a c k a g e e n t i t y ; 2 p u b l i c c l a s s I t e m { 3 p r i v a t e l o n g id ; 4 p r i v a t e S t r i n g n a m e ; 5 p r i v a t e S t r i n g d e s c r i p t i o n ;

6 p r i v a t e Set < Bid > b i d s =new HashSet < Bid > ( ) ; // se si usa Set 7 /* p r i v a t e List < Bid > b i d s = new A r r a y L i s t < Bid > ( ) ; / / se si usa Bag

8 p r i v a t e C o l l e c t i o n < Bid > b i d s =

9 new A r r a y L i s t < Bid > ( ) ; / / se si usa L i s t */

10 ...

(30)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Listing 13: Frammento di Bid.hbm.xml

1 ...

2 < p r o p e r t y n a m e =" a m o u n t " c o l u m n =" E U R O "/ >

3 < many - to - one n a m e =" i t e m " c o l u m n =" I T E M _ I D " c l a s s =" I t e m "

4 not - n u l l =" tr u e "/ >

5 ...

nel precedente listato relativo ad Item delle tre righe che definiscono l’attributo bids due devono essere commentate o rimosse per far funzionare la classe. La traduzione in schema relazionale che verrà presa in considerazione per l’analisi dei tre tipi di collezione è la seguente:

Figura 11: Schema Relazionale Item e Bid

Per tutte e tre le collezioni utilizzate tale schema relazionale è ottenibile mediante due file XML di mappatura ovvero Bid.hbm.xml e Item.hbm.xml, le differenze nei tre casi si vedono solo su Item.hbm.xml quindi nel listato 13 verrà indicato il frammento importante (quello riguardante il collegamento tra Bid e Item) di Bid.hbm.xml. Analizziamo ora le tre possibili collezioni:

1. Set: Se usiamo un Set nella classe Item.java bisogna lasciare delle tre righe relative all’attributo bids solo quello di tipo HashSet (che va importato all’inizio della classe Java). In questo caso il frammento significativo del file XML di Item è il seguente:

Listing 14: Frammento di Item.hbm.xml usando un Set

1 ... 2 < set n a m e =" b i d s " i n v e r s e =" t r u e " c a s c a d e =" save - u p d a t e "> 3 < key c o l u m n =" I T E M _ I D "/ > 4 < one - to - m a n y c l a s s =" Bid "/ > 5 < / set > 6 ...

(31)

3.4 Associazioni Binarie Uno a Molti

Listing 15: Frammento di Item.hbm.xml usando un Bag

1 ... 2 < bag n a m e =" b i d s " i n v e r s e =" t r u e " c a s c a d e =" save - u p d a t e "> 3 < key c o l u m n =" I T E M _ I D "/ > 4 < one - to - m a n y c l a s s =" Bid "/ > 5 < / bag > 6 ...

3. List: Usando una collezione di tipo List bisogna lasciare bids di tipo ArrayList cancellando gli altri nella classe Item.java. Di seguito il frammento di codice per questo caso:

Listing 16: Frammento di Item.hbm.xml usando un List

1 ... 2 < l i s t n a m e =" b i d s " i n v e r s e =" t r ue " c a s c a d e =" save - u p d a t e "> 3 < key c o l u m n =" I T E M _ I D "/ > 4 < list - i n d e x c o l u m n =" B I D _ P O S I T I O N "/ > 5 < one - to - m a n y c l a s s =" Bid "/ > 6 < / l i s t > 7 ...

3.4.2 Associazione Uno a Molti Con Partecipazioni Opzionali

Riprendiamo l’esempio del paragrafo precedente sul sito di aste online considerando la parte relativa all’informazione sul compratore di un certo oggetto. La base di dati raccoglie tutti gli utenti che interagiscono col sito e tutti gli oggetti che vi sono venduti. Chiaramente un utente può comprare più oggetti ed ogni oggetto può essere comprato da uno ed un solo utente. Questa situazione è correttamente schematizzata dallo schema Entity-Relationship di figura 12.

Figura 12: Schema E-R Item-User

(32)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Figura 13: Schema Relazionale Item-User

Listing 17: Frammento di Item.hbm.xml

1 ... 2 < j o i n t a b l e =" B U Y E R S " i n v e r s e =" t r u e "> 3 < key c o l u m n =" I T E M _ I D " u n i q u e =" t r u e " not - n u l l =" t ru e "/ > 4 < many - to - one n a m e =" b u y e r " c l a s s =" U s e r " c o l u m n =" U S E R _ I D "/ > 5 < / j o i n > 6 ...

Per realizzare correttamente la situazione c’è bisogno di due classi: Item.java (analoga all’esempio precedente) e User.java(analoga al listato 4). Le uniche differenze delle due classi rispetto agli esempi precedenti sono che per Item non c’è più l’attributo bids (che rimarrebbe se analizzassimo un problema completo) mentre c’è un attributo in più chia-mato buyer di tipo User il cui significato è evidente, per User invece abbiamo un attributo items che è un Set di Item. Per la corretta mappatura sono necessari due file XML ovvero Item.hbm.xml e User.hbm.xml (listati 17 e 18). Come si può notare dalla parte dal listato relativo ad Item.hbm.xml viene definita una tabella congiunta tra le due entità denominata BUYER, si definisce inoltre la chiave per tale tabella e il vincolo di integrità referenziale. Si tratta di un vincolo di tipo many-to-one ovvero l’altro lato della one-to-many. Nel modello relazionale non esiste il concetto di relazione many-to-one ma questo subentra quando si utilizzano Java ed Hibernate, in quanto Hibernate deve capire se un oggetto è riferito (o può esserlo) da più oggetti di un’altra classe.

Il listato relativo a User.hbm.xml invece, specificato che il Set deve essere mappato in una relazione esterna ovvero BUYER, deve definire un vincolo di integrità referenziale di tipo one-to-many utilizzando però il tag <many-to-many> ed impostando un vincolo unique=true. Tale operazione è assolutamente identica a creare una one-to-many ma l’im-plementazione di Hibernate non consente di mettere tale tag all’interno di un Set quindi per creare un vincolo uno a molti si forza il concetto di molti a molti.

3.4.3 Associazione Uno a Molti Con Attributo sull’Associazione

(33)

3.4 Associazioni Binarie Uno a Molti

Listing 18: Frammento di User.hbm.xml

1 ... 2 < set n a m e =" i t e m s " t a b l e =" B U Y E R S " c a s c a d e =" save - u p d a t e "> 3 < key c o l u m n =" U S E R _ I D " not - n u l l =" t r u e "/ > 4 < many - to - m an y c l a s s =" I t e m " c o l u m n =" I T E M _ I D " u n i q u e =" t r u e " / > 5 < / set > 6 ...

schema E-R precedente è minima come si può vedere in figura:

Figura 14: Schema E-R User - Item con prezzo di vendita In questo caso lo schema relazionale tradotto è il seguente:

Figura 15: Schema Relazionale tradotto da fig. 3.4.3

Questa piccola modifica concettuale si rivela un’enorme modifica dal punto di vista Java/-Hibernate. Non è più possibile infatti esprimere la relazione intermedia Buyer per mezzo dei tag <join>. D’altronde ora la relazione Buyer ha un attributo valido per ogni sua istanza (Amount) quindi come è possibile mettere tale attributo nella classe User.java o Item.java se questi oggetti potrebbero anche non partecipare all’associazione (e quindi non aver bisogno di un attributo Amount)??

(34)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Listing 19: Frammento di Buyer.java

1 ... 2 p u b l i c c l a s s B u y e r { 3 p u b l i c s t a t i c c l a s s Id { 4 p r i v a t e l o n g i t e m I d ; 5 p r i v a t e l o n g u s e r I d ; 6 7 // c o n s t r u c t o r s 8 p u b l i c b o o l e a n e q u a l s ( O b j e c t o ){ 9 if ( o != n u l l && o i n s t a n c e o f Id ){ 10 Id t h a t =( Id ) o ; 11 r e t u r n t hi s. i t e m I d . e q u a l s ( t h a t . i t e m I d ) 12 &&t h i s. u s e r I d . e q u a l s ( t h a t . u s e r I d ); 13 } 14 r e t u r n f a l s e; 15 } 16 p u b l i c int h a s h C o d e (){ 17 r e t u r n i t e m I d . h a s h C o d e ()+ u s e r I d . h a s h C o d e (); 18 } 19 } 20 p r i v a t e Id id =new Id (); 21 p r i v a t e U s e r u s e r ; 22 p r i v a t e I t e m i t e m ; 23 p r i v a t e d o u b l e a m o u n t ; 24 // c o n s t r u c t o r s , s e t t e r and g e t t e r 25 }

Listing 20: Frammento di Buyer.hbm.xml

1 ... 2 < c o m p o s i t e - id n a m e =" id " c l a s s =" B u y e r $ Id "> 3 < key - p r o p e r t y n a m e =" i t e m I d " a c c e s s =" f i e l d " c o l u m n =" I T E M _ I D "/ > 4 < key - p r o p e r t y n a m e =" u s e r I d " a c c e s s =" f i e l d " c o l u m n =" B U Y E R _ I D "/ > 5 < / c o m p o s i t e - id > 6 < p r o p e r t y n a m e =" a m o u n t " c o l u m n =" A M O U N T "/ >

7 < many - to - one n a m e =" u s e r " c o l u m n =" B U Y E R _ I D " not - nu l l =" t r u e "

8 i n s e r t =" f a l s e " u p d a t e =" f a l s e "/ >

9 < many - to - one n a m e =" i t e m " c o l u m n =" I T E M _ I D " not - n u ll =" t r u e "

10 i n s e r t =" f a l s e " u p d a t e =" f a l s e "/ >

(35)

3.4 Associazioni Binarie Uno a Molti

Listing 21: Frammento di Item.hbm.xml

1 ... 2 < j o i n t a b l e =" B U Y E R " i n v e r s e =" t r u e "> 3 < key c o l u m n =" I T E M _ I D " u n i q u e =" t r u e "/ > 4 < many - to - one n a m e =" b u y e r " c l a s s =" U s e r " c o l u m n =" B U Y E R _ I D "/ > 5 < / j o i n > 6 ...

Listing 22: Frammento di User.hbm.xml

1 ... 2 < set n a m e =" i t e m s " t a b l e =" B U Y E R "> 3 < key c o l u m n =" B U Y E R _ I D "/ > 4 < one - to - m a ny c l a s s =" B u y e r "/ > 5 < / set > 6 ...

poter facilitare il lavoro di Hibernate con la gestione delle query.

Il file Buyer.hbm.xml mostra come definire chiave composte e come riferirsi a campi con-tenuti in nested class. Inoltre definisce i due vincoli di integrità sulle chiavi con due <one-to-many> cosa che non è concettualmente corretta come verrà discusso dopo. I frammenti dei file di mappatura Item.hbm.xml e User.hbm.xml che completano l’esempio (le classi Item.java e User.java sono sempre le stesse) sono mostrati nei listati 21 e 22. La cosa importante da notare è l’imposizione su Item.hbm.xml attraverso il tag <join> del vincolo unique sulla chiave relativa ad Item. In questo modo si compensa lo squilibrio creato dal considerare fino a questo momento tutti vincoli come dei many-to-one. In poche parole questo esempio illustra l’unica incongruenza riscontrata tra modello relazionale e Hibernate. Infatti il modello relazionale creato in questo caso differisce da quello con cui siamo partiti per l’esempio in quanto verrà creato un modello relazionale analogo con però la relazione BUYER definita così:

Figura 16: Schema relazionale realizzato con Hibernate

(36)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

3.5 Associazioni Binarie Molti a Molti

Per associazione molti a molti si intende una associazione che coinvolge due entità con cardinalità (0,N) o (1,N) da entrambi i lati. Per questi tipi di associazione dunque si avranno da tutti e due i lati una collezione di oggetti, come già detto prima verranno usati i Set per questi esempi ma il codice è riutilizzabile anche per List e Bag modificando solo i tag come mostrato nella sez: 3.4.1.

3.5.1 Associazioni Molti a Molti Semplici

Consideriamo una base di dati relativa ad un sito web di aste online. Tale base di dati deve raccogliere al suo interno tutti gli oggetti venduti nel sito che sono organizzati in categorie. Più precisamente una categoria può contenere uno o più oggetti e un oggetto appartiene ad una o più categorie. Ecco lo schema Entity Relationship che descrive la situazione:

Figura 17: Schema E-R Category - Item Lo schema relazionale tradotto è il seguente:

Figura 18: Schema Relazionale Category - Item

(37)

3.5 Associazioni Binarie Molti a Molti

Listing 23: Frammento Category.java

1 ...

2 p u b l i c c l a s s C a t e g o r y { 3 p r i v a t e l o n g id ; 4 p r i v a t e S t r i n g n a m e ;

5 p r i v a t e Set < Item > i t e m s =new HashSet < Item > ( ) ; 6 // c o n s t r u c t o r s , s e t t e r and g e t t e r

7 }

Listing 24: Frammento Item.java

1 ...

2 p u b l i c c l a s s I t e m { 3 p r i v a t e S t r i n g n a m e ; 4 p r i v a t e l o n g id ;

5 p r i v a t e S t r i n g d e s c r i p t i o n ;

6 p r i v a t e Set < Ca t e g o r y > c a t e g o r i e s =new HashSet < C a t e g o r y > ( ) ; 7 // c o n s t r u c t o r s , s e t t e r and g e t t e r

8 }

Listing 25: Frammento Category.hbm.xml

1 ... 2 < set n a m e =" i t e m s " t a b l e =" C A T E G O R Y _ I T E M " c a s c a d e =" save - u p d a t e "> 3 < key c o l u m n =" C A T E G O R Y _ I D "/ > 4 < many - to - m an y c l a s s =" I t e m " c o l u m n =" I T E M _ I D "/ > 5 < / set > 6 ...

Listing 26: Frammento Item.hbm.xml

(38)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

mappatura la chiave dell’altra entità si crea alla fine una relazione con una chiave doppia composta dai due identificatori delle classi Item e Category.

3.5.2 Associazioni Molti a Molti con Attributi Comuni

Consideriamo lo stesso esempio di prima volendo però tenere conto della data di quando è stato aggiunto un oggetto in una categoria. Tale situazione viene illustrata nel seguente E-R con lo schema relazionale ottenuto:

Figura 19: Schema ER Item - Category

Figura 20: Schema Relazionale Item - Category

Questa piccola modifica come già visto per l’esempio trattato nella sezione 3.4.3 complica le cose dal punto di vista di Hibernate poichè c’è bisogno di un ulteriore classe Catego-ry_Item.java e di un ulteriore file di configurazione ma in questo caso lo schema relazionale proposto viene correttamente tradotto.

E’ presente questa differenza rispetto a prima perchè il metodo utilizzato per mappare una associazione uno a molti con attributi comuni è nativo per le associazioni molti a molti con attributi comuni.

(39)

3.5 Associazioni Binarie Molti a Molti

Listing 27: Frammento classe CategorizedItem.java

1 ... 2 p u b l i c c l a s s C a t e g o r i z e d I t e m { 3 p u b l i c s t a t i c c l a s s Id { 4 p u b l i c l on g c a t e g o r y I d ; 5 p u b l i c l on g i t e m I d ; 6 // c o n s t r u c t o r s 7 // m e t o d i h a s h C o d e e e q u a l s 8 } 9 p r i v a t e Id id ; 10 p r i v a t e D a t e d a t e a d d e d ; 11 p r i v a t e I t e m i t e m ; 12 p r i v a t e C a t e g o r y c a t e g o r y ; 13 // c o n s t r u c t o r s , g e t t e r and s e t t e r 14 }

Listing 28: Frammento Category.hbm.xml

1 ... 2 < set n a m e =" c a t e g o r i z e d I t e m s " i n v e r s e =" t r u e "> 3 < key c o l u m n =" C A T E G O R Y _ I D "/ > 4 < one - to - m a ny c l a s s =" C a t e g o r i z e d I t e m "/ > 5 < / set > 6 ...

Listing 29: Frammento Item.hbm.xml

(40)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Listing 30: Frammento CategorizedItem.hbm.xml

1 ... 2 < c o m p o s i t e - id n a m e =" id " c l a s s =" C a t e g o r i z e d I t e m $ Id "> 3 < key - p r o p e r t y n a m e =" c a t e g o r y I d " c o l u m n =" C A T E G O R Y _ I D " 4 a c c e s s =" f i e l d "/ > 5 < key - p r o p e r t y n a m e =" i t e m I d " c o l u m n =" I T E M _ I D " a c c e s s =" f i e l d "/ > 6 < / c o m p o s i t e - id > 7 < p r o p e r t y n a m e =" d a t e A d d e d " ty p e =" t i m e s t a m p " not - n u l l =" t r u e "/ > 8 < many - to - one n a m e =" c a t e g o r y " c o l u m n =" C A T E G O R Y _ I D " not - n u l l =" t r u e "

9 i n s e r t =" f a l s e " u p d a t e =" f a l s e " / >

10 < many - to - one n a m e =" i t e m " c o l u m n =" I T E M _ I D " not - n u ll =" t r u e "

11 i n s e r t =" f a l s e " u p d a t e =" f a l s e "/ >

12 ...

all’associazione uno a molti con tabella intermedia appunto perchè il metodo usato per quell’esempio è nativo per questo.

3.6 Associazioni Ternarie

Per associazione ternaria si intende un’associazione che coinvolge tre entità con cardinalità (1,N) o (0,N) da tutti e tre i lati dell’associazione. Non verranno trattati i casi diversi in quanto è conveniente tradurre tali casi con associazioni binarie.

Consideriamo l’ultimo esempio che coinvolgeva oggetti e categorie e supponiamo di voler aggiungere l’informazione riguardante gli utenti che hanno aggiunto certi item nelle cate-gorie afferenti.

Siamo nel caso di un’associazione ternaria schematizzata dallo schema Entity-Relationship di figura 21 mentre in figura 22 è mostrato lo schema relazionale che verrà implementato con Hibernate.

Questo caso è gestibile in modo simile al caso di molti a molti con tabella intermedia. Per poter quindi mappare correttamente la situazione sono necessari otto file totali ovvero:

• Quattro classi Java (Item.java, Category.java, User.java e CategorizedItem.java) che non verranno mostrate in quanto simili al caso precedente (ogni classe ha un Set di elementi chiamati categorizedItems di tipo Set<CategorizedItem> e CategorizedItem avrà una nested class in cui si costruisce l’identificatore con l’insieme dei tre id della altre tre classi).

(41)

3.6 Associazioni Ternarie

Listing 31: Frammento di User.hbm.xml

1 ... 2 < set n a m e =" c a t e g o r i z e d I t e m s " i n v e r s e =" t r u e "> 3 < key c o l u m n =" A D D E D _ B Y "/ > 4 < one - to - m a ny c l a s s =" C a t e g o r i z e d I t e m "/ > 5 < / set > 6 ...

Listing 32: Frammento di Category.hbm.xml

1 ... 2 < set n a m e =" c a t e g o r i z e d I t e m s " i n v e r s e =" t r u e "> 3 < key c o l u m n =" C A T E G O R Y _ I D "/ > 4 < one - to - m a ny c l a s s =" C a t e g o r i z e d I t e m "/ > 5 < / set > 6 ...

Listing 33: Frammento di Item.hbm.xml

(42)

3 IMPLEMENTAZIONE DI SCHEMI RELAZIONALI CON HIBERNATE

Figura 21: Schema Entity Relationship Item - Category - User

Figura 22: Schema Relazionale Item - Category

Da notare nei file di mappatura la presenza di update=false ed insert=false nel file di mappatura CategorizedItem.hbm.xml nella definizione dei vincoli di integrità referenziale. Tali comandi sono imposti da Hibernate in quanto la relazione Categorized_Item si inten-de sia una relazione le cui tuple vengono create alla creazione di un’associazione tra un utente e una coppia (categoria, oggetto) e quindi si presuppone che l’associazione sia non modificabile.

Infatti la riga dichiarativa del file CategorizedItem2.hbm.xml contiene mutable=false che sta a significare proprio quello appena descritto.

(43)

3.6 Associazioni Ternarie

Listing 34: Frammento di CategorizedItem.hbm.xml

(44)
(45)

4

Conclusioni

Dopo aver implementato e testato tutti gli esempi di questa tesi, Hibernate è risultato un ottimo tool per il colloquio tra applicazioni Java e Database che però presenta qualche svantaggio.

Uno dei suo obiettivi primari, che è risultato essere quello più evidente tra quelli proposti dagli sviluppatori, è la notevole riduzione delle righe di codice necessarie per colloquiare con uno o più database e soprattutto l’elevato tasso di riutilizzo del codice.

Quest’ultimo punto infatti risulta essere, a mio parere, determinante per chi vuole affac-ciarsi all’uso di Hibernate, ed è evidente soprattutto per chi deve scrivere molte applicazioni diverse ognuna delle quali agganciata ad un database. Il tempo che si risparmia riutiliz-zando tutto il codice ripetitivo tramite dei semplici drag and drop può essere utilizzato per affinare l’applicazione e per concentrarsi sui business problems ovvero sui problemi relativi all’applicazione e non sul colloquio di essa col database.

Un altro vantaggio che ho potuto confermare in questa tesi è come Hibernate mantenga estremamente leggibili le classi che devono essere rese persistenti e come mantenga tutto il progetto perfettamente scalabile e adattabile alle modifiche inevitabili che possono capitare nel ciclo di vita di un’applicazione.

Per quanto riguarda il miglior controllo delle performance, ciò si ha solamente se viene utilizzato c3p0 o un Database Connection Pool alternativo e ciò non è necessario affinchè Hibernate funzioni correttamente. Tale obiettivo quindi non è assimibilabile ad Hibernate, può comunque essere l’ago della bilancia per molti applicativi che colloquiano con database da milioni di tuple concorrentemente tra molti utenti.

Per quanto riguarda gli aspetti negativi di Hibernate si è notata una certa lentezza nel-l’avvio e nel mantenere il colloquio con i database. In generale confrontando la soluzione del colloquio attraverso connessioni JDBC all’interno del codice e con Hibernate, la prima soluzione risulta essere più performante dal punto di vista della velocità d’esecuzione. Ciò è anche spiegabile dal fatto che Hibernate è un insieme di classi ed interfacce che si frappo-ne tra codice Java e Database che al suo interno usa confrappo-nessioni JDBC, quindi quando si aggiunge uno strato aggiuntivo ad un qualcosa che funziona ad una certa velocità è logico aspettarsi che quello che si ottiene diminuisca la velocità di esecuzione.

(46)

4 CONCLUSIONI

di vista semantico che si traduce solo in un vincolo in più sul database mentre non ci sono differenze dal punto di vista operativo.

(47)

5

Bibliografia

Riferimenti bibliografici

[1] Christian Bauer, Gavin King, Java Persistence With Hibernate ed. Manning, 2007;

[2] Atzeni, Ceri, Paraboschi, Torlone Basi di Dati Modelli e Linguaggi di

Programmazione, ed. McGraw-Hill;

[3] Elmasri, Navathe Sistemi di Basi di Dati ed. Pearson, 2011;

[4] Cay Horstmann Concetti di informatica e fondamenti di Java ed. Apogeo; [5] Wikipedia: http://www.wikipedia.com;

[6] Java: http://www.java.com;

[7] Hibernate: http://www.Hibernate.org; [8] Eclipse: http://www.eclipse.org;

Riferimenti

Documenti correlati

In Byob i dati di prima classe sono molti di più, si utilizzano quindi ingressi di molti più tipi, che comprendono anche procedure, liste e oggetti.. Richiamiamo ora la descrizione

We used the LIVE IQA database [27] to test the perfor- mance of BRISQUE, which consists of 29 reference images with 779 distorted images spanning five different distortion categories

Nel metodo di tracking, al ritorno della chiamata a Camshift, disponiamo dell’area oltre che delle coordinate del centro del rettangolo che contiene l’oggetto, questo permette

Nell'esecuzione di richieste al server PHP è quindi più favorita perché può fare delle richieste SOAP o REST che non fanno altro che eseguire altro codice PHP (nel nostro caso vi

L’applicazione classica dell’albero dei suffissi è la soluzione del “problema della sottostringa”, ossia: dato un testo T di lunghezza m, dopo un tempo di preelaborazione

A character device driver and a user space application have been developed to handle the MCC communication on the Linux side and visualize the data received from the Cortex-M4.

Come conseguenza ai lavori precedenti e alle problematiche riscontrate (dataset sporco, rilevazione multipla di una stessa discontinuità, rete neurale ecces- sivamente grande per

Dal punto di vista prestazionale, l’aspetto più oneroso riguarda l’utilizzo di file grafici per la rappresentazione della simbologia: a causa della gestione delle immagini da parte