2013-04-20 19 views
25

Attualmente sto leggendo la documentazione di Hibernate riguardante lo entity associations e ho incontrato un po 'di difficoltà per capire alcune cose. Deve essenzialmente fare la differenza tra le associazioni ManyToOne e OneToMany. Sebbene li abbia usati in progetti reali, non riesco a comprendere completamente la differenza tra loro. A mio avviso, se una tabella/un'entità ha un'associazione ManyToOne con un'altra, l'associazione dovrebbe essere dall'altra parte OneToMany. Quindi, come dovremmo decidere quale scegliere in base a un caso specifico e in che modo influisce sul database/query/risultati? C'è ovunque un buon esempio?Hibernate/JPA ManyToOne vs OneToMany

P.S .: Penso che sarebbe utile per la sua pertinenza alla domanda, se qualcuno potesse oltre a spiegare qual è il punto del proprietario dell'associazione e la differenza tra associazione bidirezionale e unidirezionale.

risposta

43

Supponiamo che tu abbia un ordine e un ordine. È possibile scegliere di disporre di OneToMany unidirezionale tra Order e OrderLine (l'ordine avrebbe una raccolta di OrderLines). Oppure puoi scegliere di avere un'associazione ManyToOne tra OrderLine e Order (OrderLine avrebbe un riferimento al suo Ordine). Oppure puoi scegliere di avere entrambi, nel qual caso l'associazione diventa un'associazione bidirezionale OneToMany/ManyToOne.

La soluzione scelta dipende principalmente dalla situazione e dal livello di accoppiamento tra le entità. Ad esempio, se un utente, un'azienda, un fornitore hanno tutti molti indirizzi, avrebbe senso avere un unidirezionale tra ognuno di essi e l'indirizzo, e avere l'indirizzo non conoscere il loro proprietario.

Supponiamo che tu abbia un utente e un messaggio, in cui un utente può avere migliaia di messaggi, potrebbe avere senso modellarlo solo come ManyToOne da Messaggio all'utente, perché raramente chiedi tutti i messaggi di un utente comunque. L'associazione può essere resa bidirezionale solo per aiutare con le query, poiché le query JPQL si uniscono tra le entità navigando attraverso le loro associazioni.

In un'associazione bidirezionale, potresti trovarti in una situazione in cui il grafico degli oggetti è incoerente. Ad esempio, l'Ordine A avrebbe un set vuoto di OrderLines, ma alcuni OrderLines avrebbero un riferimento all'Ordine A. JPA impone di avere sempre un lato dell'associazione che è il lato proprietario, e l'altro lato è il lato inverso. Il lato inverso viene ignorato dall'APP. Il lato proprietario è la parte che decide quale relazione esiste. In un'associazione bidirezionale OneToMany, il lato proprietario deve essere il lato più. Quindi, nell'esempio precedente, il lato proprietario sarebbe OrderLine e JPA avrebbe mantenuto l'associazione tra le righe e l'ordine A, poiché le linee hanno un riferimento a A.

Tale associazione verrebbe mappata in questo modo:

nell'ordine:

@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the 
    // inverse side, and that the mapping is defined by the attribute parentOrder 
    // at the other side of the association. 
private Set<OrderLine> lines; 

in OrderLine:

@ManyToOne 
private Order parentOrder; 
1

Inoltre, avendo @ManytoOne lato come proprietario richiederebbe soltanto n + 1 q cerca durante il salvataggio delle associazioni. Dove n è il numero di associazioni (molti lati).

Considerando che avere @OneToMany come proprietario, mentre si inserisce l'entità padre (un lato) con associazioni (molti lati) si otterrebbero query 2 * N + 1. In quale una query sarebbe per l'inserimento dell'associazione e altra query sarebbe per l'aggiornamento della chiave esterna nell'entità associata.