Mapping delle Relazioni in Hibernate

Nell’articolo Primi Passi con Hibernate sono stati introdotti i concetti che sono alla base dell’utilizzo del framework ORM Hibernate, mostrando un semplice esempio di mapping di una singola entità. In questo post affrontiamo il problema del mapping delle diverse possibili relazioni tra persisted object.

Associazioni in Java

Hibernate è un framework di persistenza per plain java object (o pojo) e quindi le tipologie di associazioni che sono prese in considerazione sono prevalentemente quelle unidirezionali, tipiche di java. Tali associazioni sono tipicamente espresse attraverso riferimenti o collezioni in funzione della molteplicità dell’associazione. La specifica JPA prevede le seguenti tipologie di associazioni:

ONE-TO-ONE Ogni istanza di una entità è legata ad una singola istanza di un’altra entità. Sono espresse attraverso l’annotazione javax.persistence.OneToOne posizionata in corrispondenza  della proprietà o campo dell’oggetto persistito.
ESEMPIO: relazione tra una persona ed il proprio passaporto.
 ONE-TO-MANY Un’istanza di una entità può essere correlata a più istanze di altre entità. Sono espresse utilizzando l’annotazione javax.persistence.OneToMany posizionata in corrispondenza  della proprietà o campo dell’oggetto persistito.
ESEMPIO: relazione esistente tra un ordine di acquisto e gli elementi che lo compongono.
 MANY-TO-ONE Più istanze di una entità possono essere correlati a una singola istanza dell’altra entità. Questa molteplicità è l’opposto di una relazione one-to-many. Sono espresse utilizzando l’annotazione javax.persistence.ManyToOne posizionata in corrispondenza della proprietà o campo dell’oggetto persistito.
ESEMPIO: relazione esistente tra una persona ed uno dei suoi genitori, che ovviamente può avere più figli.
 MANY-TO-MANY Le istanze di una entità possono essere correlate a più istanze di ogni altro entità. Sono espresse attraverso l’annotazione javax.persistence.ManyToMany posizionata in corrispondenza della proprietà o campo dell’oggetto persistito.
ESEMPIO: la relazione che college ogni corso ha molti studenti, e ogni studente hai diversi corsi che frequenta.

Le diverse associazioni sono caratterizzate da informazioni che sono caratteristiche della specifica relazione, ma tutte hanno in comune la modalità con cui sono recuperate dal database (fetching). L’enum FetchType elenca le due strategie possibili di fetching, che sono EAGER o LAZY. La prima indica al runtime di persistenza che la relazione deve essere recuperata immediatamente insieme all’oggetto che la utilizza. La seconda è invece un suggerimento per cui la specifica implementazione può decidere di seguirlo, recuperando la relazione solamente quando viene acceduta, o meno, di fatto comportandosi come nel caso EAGER.

Relazione One-To-One

Consideriamo la relazione esistente tra uno studente e l’indirizzo della sua abitazione, rappresentato dal modello dati mostrato in figura, dove un indirizzo è associato univocamente ad uno studente.

one to one studente-indirizzo

Lo script di creazione delle due tabelle e della relazione in una base dati MySQL sarà:

Utilizzando le annotation il mapping tra la classe Studente ed Indirizzo sarà del tipo:
Si noti che nella relazione è stato specificata EAGER come strategia di fetching ma, più importante, è stata utilizzata l’annotazione @JoinColumn per indicare la colonna della tabella STUDENTI che contiene il valore della primary key referenziata nella tabella INDIRIZZI.

Recuperare lo studente ed il relativo indirizzo è quindi possibile semplicemente con una unica istruzione:

Sebbene non necessario è anche possibile mappare la relazione inversa tra l’indirizzo e lo studente cui è associato, senza necessità di modificare il database ma semplicemente utilizzando la stessa annotation sulla classe Indirizzo nel modo seguente:

In questo caso è sufficiente indicare la proprietà della classe Studente che mappa la relazione ed Hibernate provvederà ad invertirla per eseguire la join necessaria a recuperala. Il codice seguente produce esattamente lo stesso output del precedente:

Relazione One-To-Many e Many-To-One

Consideriamo la relazione esistente tra uno studente ed il relativo corso di laurea, mostrata nel modello dati seguente, dove un ad un corso possono essere iscritti più studenti ma uno studente può appartenere ad uno ed un solo corso di laurea.

studenti-corsi many to one e one to many

Si noti che la struttura della tabella CORSI_LAUREA è similare a quella INDIRIZZI, quindi la differenziazione del tipo di relazione deve essere fatta a livello di mapping JPA. Modifichiamo il database con il seguente script:

Utilizzando le annotazioni JPA il mapping tra le classi Studente e CorsoLaurea si realizzeranno attraverso una annotazione @ManyToOne sulla prima classe:

ed una @OneToMany sulla seconda:

Anche in questo caso è necessario, quindi, specificare la colonna di join nella relazione @ManyToOne presente nella classe Studente e la proprietà di mapping nella @OneToMany nella classe CorsoLaurea.

Il seguente codice mostra come recuperare Il corso di laurea di uno studente e tutti gli studenti appartenenti ad uno specifico corso di laurea:

Relazione Many-To-Many

Questa volta prendiamo in consideriamo la relazione esistente tra uno studente ed i corsi di studio seguiti. In questo caso uno studente può seguire più corsi ed analogamente ad un corso possono essere iscritti più studenti. Una relazione di questo tipo può essere catturata esclusivamente utilizzando una tabella di relazione tra le due entità, come mostrato nel diagramma seguente:

studenti-corsi-iscritti many-to-many

Aggiorniamo il nostro database con lo script seguente di creazione delle due tabelle CORSI_STUDIO e STUDENTI_CORSO:

Supponiamo ora di voler mappare nella classe Studente tutti i corsi di studio seguiti. Per farlo utilizziamo l’annotazione @ManyToMany nel modo seguente:

Si noti che la tabella STUDENTI_CORSO non ha un corrispondente model nel progetto ma è semplicemente referenziata dall’annotazione @JoinTable che serve a dichiarare il mapping tra le entità Studente e CorsoStudio.

Il codice seguente recupera uno studente e stampa a video i corsi seguiti:

Codice Sorgente

Il codice sorgente comprensivo dello script SQL di creazione del database è disponibile qui hb-user.

How useful was this post?

Click on a star to rate it!

Average rating 3.4 / 5. Vote count: 7

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

2 Comments

    1. Buongiorno.
      Mi rendo conto che il mapping delle gerarchie è un argomento altrettanto interessante. Preparerò quindi un post a breve.
      Grazie.

Comments are closed.