Articles

Hibernate One to Many Annotation Tutorial

Introduzione

Questo breve Hibernate tutorial ci porterà attraverso un esempio di una mappatura uno-a-molti utilizzando JPA annotazioni, un’alternativa a XML.

Impareremo anche quali sono le relazioni bidirezionali, come possono creare incongruenze e come l’idea di proprietà può aiutare.

Ulteriori letture:

Avvio a molla con Hibernate

Un’introduzione rapida e pratica all’integrazione di Spring Boot e Hibernate / JPA.
Per saperne di più →

Una panoramica degli identificatori in Hibernate/JPA

Scopri come mappare gli identificatori di entità con Hibernate.
Leggi di più →

Descrizione

In poche parole, la mappatura uno-a-molti significa che una riga in una tabella viene mappata su più righe in un’altra tabella.

Diamo un’occhiata al seguente diagramma delle relazioni di entità per vedere un’associazione uno-a-molti:

Per questo esempio, implementeremo un sistema di carrello in cui abbiamo una tabella per ogni carrello e un’altra tabella per ogni articolo. Un carrello può avere molti articoli, quindi qui abbiamo una mappatura uno-a-molti.

Il modo in cui funziona a livello di database è che abbiamo un cart_id come chiave primaria nella tabella cart e anche un cart_id come chiave esterna negli elementi.

Il modo in cui lo facciamo nel codice è con @OneToMany.

Mappiamo la classe Cart all’oggetto Items in un modo che riflette la relazione nel database:

public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; //...}

Possiamo anche aggiungere un riferimento al Cart in Items usando @ManyToOne, rendendo questa relazione bidirezionale. Bidirezionale significa che siamo in grado di accedere agli articoli dai carrelli e anche ai carrelli dagli articoli.

La proprietà mappedBy è ciò che usiamo per dire a Hibernate quale variabile stiamo usando per rappresentare la classe genitore nella nostra classe figlio.

Le seguenti tecnologie e librerie vengono utilizzate per sviluppare un’applicazione di Hibernate di esempio che implementa l’associazione uno a molti:

  • JDK 1.8 o successivo
  • Hibernate 5
  • Maven 3 o successivo
  • H2 database

Setup

3.1. Configurazione del database

Di seguito è riportato il nostro script di database per le tabelle Carrello e articoli. Usiamo il vincolo della chiave esterna per la mappatura uno-a-molti:

La nostra configurazione del database è pronta, quindi passiamo alla creazione del progetto di esempio Hibernate.

3.2. Dipendenze Maven

Aggiungeremo quindi le dipendenze del driver Hibernate e H2 al nostro pom.file xml. La dipendenza Hibernate utilizza la registrazione JBoss e viene automaticamente aggiunta come dipendenze transitive:

  • Hibernate versione 5.2.7.Finale
  • H2 versione del driver 1.4.197

Si prega di visitare il repository centrale Maven per le ultime versioni di Hibernate e le dipendenze H2.

3.3. Configurazione Hibernate

Ecco la configurazione di Hibernate:

3.4. HibernateAnnotationUtil Class

Con la classe HibernateAnnotationUtil, abbiamo solo bisogno di fare riferimento al nuovo file di configurazione di Hibernate:

I modelli

Le configurazioni relative alla mappatura verranno eseguite utilizzando le annotazioni JPA nelle classi del modello:

@Entity@Table(name="CART")public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; // getters and setters}

Si noti che l’annotazione @OneToMany viene utilizzata per definire la proprietà nella classe Items che verrà utilizzata per mappare la variabile mappedBy. Questo è il motivo per cui abbiamo una proprietà denominata “cart” nella classe Items:

È anche importante notare che l’annotazione @ManyToOne è associata alla variabile della classe Cart. L’annotazione @ JoinColumn fa riferimento alla colonna mappata.

In Azione

il programma di test, ci sono la creazione di una classe con un metodo main() per ottenere la Sospensione della Sessione, e salvare il modello di oggetti nel database implementazione di uno-a-molti associazione:

Questo è l’output del nostro programma di test:

@ManyToOne Annotazione

Come abbiamo visto nella sezione 2, si può specificare una molti-a-una relazione utilizzando la @ManyToOne annotazione. Una mappatura molti-a-uno significa che molte istanze di questa entità sono mappate a un’istanza di un’altra entità – molti elementi in un carrello.

L’annotazione @ManyToOne ci consente anche di creare relazioni bidirezionali. Tratteremo questo in dettaglio nelle prossime sottosezioni.

6.1. Incongruenze e proprietà

Ora, se il carrello fa riferimento agli articoli, ma gli articoli non fanno a loro volta riferimento al Carrello, la nostra relazione sarebbe unidirezionale. Gli oggetti avrebbero anche una consistenza naturale.

Nel nostro caso, però, la relazione è bidirezionale, portando la possibilità di incoerenza.

Immaginiamo una situazione in cui uno sviluppatore vuole aggiungere item1 al carrello e item2 a cart2, ma commette un errore in modo che i riferimenti tra cart2 e item2 diventino incoerenti:

Come mostrato sopra, item2 fa riferimento a cart2, mentre cart2 non fa riferimento a item2, e questo è male.

Come dovrebbe Hibernate salvare item2 nel database? La chiave esterna item2 farà riferimento a cart1 o cart2?

Risolviamo questa ambiguità usando l’idea di un lato proprietario della relazione; i riferimenti appartenenti al lato proprietario hanno la precedenza e vengono salvati nel database.

6.2. Elementi come il lato proprietario

Come indicato nella specifica JPA nella sezione 2.9, è una buona pratica contrassegnare il lato many-to-one come lato proprietario.

In altre parole, gli elementi sarebbero il lato proprietario e il carrello il lato inverso, che è esattamente quello che abbiamo fatto in precedenza.

Quindi come abbiamo raggiunto questo obiettivo?

Includendo l’attributo mappedBy nella classe Cart, lo contrassegniamo come il lato inverso.

Allo stesso tempo, annotiamo anche gli Elementi.campo del carrello con @ ManyToOne, rendendo gli oggetti il lato proprietario.

Tornando al nostro esempio di “incoerenza”, ora Hibernate sa che il riferimento di item2 è più importante e salverà il riferimento di item2 al database.

Controlliamo il risultato:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=2

Sebbene cart faccia riferimento a item2 nel nostro snippet, il riferimento di item2 a cart2 viene salvato nel database.

6.3. Carrello come lato proprietario

È anche possibile contrassegnare il lato uno-a-molti come lato proprietario e molti-a-uno come lato inverso.

Anche se questa non è una pratica consigliata, andiamo avanti e fare un tentativo.

Il frammento di codice riportato di seguito mostra l’implementazione del lato one-to-many come lato proprietario:

Si noti come abbiamo rimosso l’elemento mappedBy e impostato il many-to-one @JoinColumn come inseribile e aggiornabile su false.

Se eseguiamo lo stesso codice, il risultato sarà il contrario:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=1

Come mostrato sopra, ora item2 appartiene al carrello.

Conclusione

Abbiamo visto quanto sia facile implementare la relazione uno-a-molti con il database Hibernate ORM e H2 usando le annotazioni JPA.

Inoltre, abbiamo imparato a conoscere le relazioni bidirezionali e come implementare la nozione di un lato proprietario.