Relazioni tra tabelle e relazioni tra entità
In un sistema di database relazionale, possono esserci solo tre tipi di relazioni tra tabelle:
- uno-a-molti (tramite una colonna chiave esterna)
- one-to-one (tramite una chiave primaria condivisa)
- molti-a-molti (tramite una tabella di collegamenti con due chiavi esterne che fanno riferimento a due tabelle padre separate)
Quindi, una one-to-many
relazione di tabella appare come segue:
Si noti che la relazione si basa sulla colonna Chiave esterna (ad esempio, post_id
) nella tabella figlio.
Quindi, c'è una sola fonte di verità quando si tratta di gestire una one-to-many
relazione tra tavoli.
Ora, se prendi una relazione di entità bidirezionale che mappa sulla one-to-many
relazione di tabella che abbiamo visto in precedenza:
Se dai un'occhiata al diagramma sopra, puoi vedere che ci sono due modi per gestire questa relazione.
Nella Post
entità, si ha la comments
collezione:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
E, in PostComment
, l' post
associazione è mappata come segue:
@ManyToOne(
fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;
Quindi, hai due lati che possono cambiare l'associazione entità:
- Aggiungendo una voce nella
comments
raccolta figlio, una nuova post_comment
riga dovrebbe essere associata post
all'entità padre tramite la sua post_id
colonna.
- Impostando la
post
proprietà PostComment
dell'entità, anche la post_id
colonna dovrebbe essere aggiornata.
Poiché esistono due modi per rappresentare la colonna Chiave esterna, è necessario definire qual è la fonte della verità quando si tratta di tradurre la modifica dello stato dell'associazione nella modifica equivalente del valore della colonna Chiave esterna.
MappedBy (aka il lato inverso)
L' mappedBy
attributo indica che la @ManyToOne
parte è incaricata di gestire la colonna Chiave esterna e la raccolta viene utilizzata solo per recuperare le entità figlio e per trasferire in cascata le modifiche dello stato dell'entità padre ai figli (ad esempio, la rimozione del genitore dovrebbe anche rimuovere le entità figlio).
Si chiama il lato inverso perché fa riferimento alla proprietà dell'entità figlio che gestisce questa relazione di tabella.
Sincronizza entrambi i lati di un'associazione bidirezionale
Ora, anche se hai definito l' mappedBy
attributo e l' @ManyToOne
associazione lato figlio gestisce la colonna Chiave esterna, devi comunque sincronizzare entrambi i lati dell'associazione bidirezionale.
Il modo migliore per farlo è aggiungere questi due metodi di utilità:
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
I metodi addComment
e removeComment
assicurano che entrambe le parti siano sincronizzate. Pertanto, se aggiungiamo un'entità figlio, l'entità figlio deve puntare al genitore e l'entità genitore dovrebbe avere il figlio contenuto nella raccolta figlio.
Per ulteriori dettagli sul modo migliore per sincronizzare tutti i tipi di associazione di entità bidirezionali, consulta questo articolo .