Questa è una domanda molto comune, quindi questa risposta si basa su questo articolo che ho scritto sul mio blog.
Uno-a-molti
La relazione della tabella uno-a-molti ha il seguente aspetto:

In un sistema di database relazionale, una relazione da una a molte tabelle collega due tabelle basate su una Foreign Keycolonna nel figlio che fa riferimento alla Primary Keyriga della tabella padre.
Nel diagramma della tabella sopra, la post_idcolonna nella post_commenttabella ha una Foreign Keyrelazione con la colonna postID tabella Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
@ManyToOne annotation
Il modo migliore per mappare la relazione della tabella uno-a-molti è utilizzare l' @ManyToOneannotazione.
Nel nostro caso, l'entità figlio, PostCommentmappa la post_idcolonna Chiave esterna usando l' @ManyToOneannotazione:
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
}
Utilizzo @OneToManydell'annotazione JPA
Solo perché hai la possibilità di utilizzare l' @OneToManyannotazione, ciò non significa che questa dovrebbe essere l'opzione predefinita per ogni relazione di database uno-a-molti . Il problema con le raccolte è che possiamo usarle solo quando il numero di record figlio è piuttosto limitato.
Il modo migliore per mappare @OneToManyun'associazione è fare affidamento sul @ManyToOnelato per propagare tutte le modifiche allo stato dell'entità:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
L'entità padre Postpresenta due metodi di utilità (ad es. addCommentE removeComment) che vengono utilizzati per sincronizzare entrambi i lati dell'associazione bidirezionale. Dovresti sempre fornire questi metodi ogni volta che lavori con un'associazione bidirezionale poiché, altrimenti, rischi di presentare problemi di propagazione dello stato molto sottili .
L' @OneToManyassociazione unidirezionale deve essere evitata in quanto è meno efficiente dell'utilizzo @ManyToOneo @OneToManydell'associazione bidirezionale .
Per ulteriori dettagli sul modo migliore per mappare la @OneToManyrelazione con JPA e Hibernate, consulta questo articolo .
Uno a uno
La relazione della tabella uno a uno ha il seguente aspetto:

In un sistema di database relazionale, una relazione di tabella uno a uno collega due tabelle basate su una Primary Keycolonna nel figlio che fa anche Foreign Keyriferimento alla Primary Keyriga della tabella padre.
Pertanto, possiamo dire che la tabella figlio condivide la Primary Keycon la tabella padre.
Nel diagramma della tabella sopra, la idcolonna nella post_detailstabella ha anche una Foreign Keyrelazione con la colonna della posttabella id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Utilizzo dell'APP @OneToOnecon @MapsIdannotazioni
Il modo migliore per mappare una @OneToOnerelazione è usare @MapsId. In questo modo, non è nemmeno necessaria un'associazione bidirezionale poiché è sempre possibile recuperare l' PostDetailsentità utilizzando l' Postidentificatore di entità.
La mappatura è simile alla seguente:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") PostDetails di classe pubblica {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
} [/codice]
In questo modo, la idproprietà funge sia da chiave primaria che da chiave esterna. Noterai che la @Idcolonna non utilizza più @GeneratedValueun'annotazione poiché l'identificatore è popolato con l'identificatore postdell'associazione.
Per ulteriori dettagli sul modo migliore per mappare la @OneToOnerelazione con JPA e Hibernate, consulta questo articolo .
Molti-a-molti
La relazione della tabella molti-a si presenta come segue:

In un sistema di database relazionale, una relazione di tabella molti-a-molti collega due tabelle padre tramite una tabella figlio che contiene due Foreign Keycolonne che fanno riferimento alle Primary Keycolonne delle due tabelle padre.
Nel diagramma della tabella sopra, la post_idcolonna nella post_tagtabella ha anche una Foreign Keyrelazione con la colonna postID tabella Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Inoltre, la tag_idcolonna nella post_tagtabella ha una Foreign Keyrelazione con la colonna tagID tabella Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Utilizzo del @ManyToManymapping JPA
Ecco come è possibile mappare la many-to-manyrelazione della tabella con JPA e Hibernate:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
//Getters and setters ommitted for brevity
public void addTag(Tag tag) {
tags.add(tag);
tag.getPosts().add(this);
}
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getPosts().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Post)) return false;
return id != null && id.equals(((Post) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@ManyToMany(mappedBy = "tags")
private Set<Post> posts = new HashSet<>();
//Getters and setters ommitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
- L'
tagsassociazione Postnell'entità definisce solo i tipi PERSISTe in MERGEcascata. Come spiegato in questo articolo , la REMOVE transizione dello stato dell'entità non ha alcun senso per un'associazione @ManyToManyJPA poiché potrebbe innescare una cancellazione della catena che alla fine cancellerebbe entrambi i lati dell'associazione.
- Come spiegato in questo articolo , i metodi di utilità Aggiungi / Rimuovi sono obbligatori se si utilizzano associazioni bidirezionali in modo da poter assicurarsi che entrambi i lati dell'associazione siano sincronizzati.
- L'
Postentità utilizza l'identificatore di entità per l'uguaglianza poiché non dispone di alcuna chiave aziendale univoca. Come spiegato in questo articolo , è possibile utilizzare l'identificatore di entità per l'uguaglianza purché si assicuri che rimanga coerente in tutte le transizioni di stato dell'entità .
- L'
Tagentità ha una chiave aziendale univoca contrassegnata con l' @NaturalIdannotazione specifica di Hibernate . In tal caso, la chiave aziendale unica è il miglior candidato per i controlli di uguaglianza .
- L'
mappedByattributo postsdell'associazione Tagnell'entità indica che, in questa relazione bidirezionale, l' Postentità possiede l'associazione. Ciò è necessario poiché solo una parte può possedere una relazione e le modifiche vengono propagate al database solo da questa parte specifica.
- È
Setpreferibile, poiché l'uso di Listcon @ManyToManyè meno efficiente.
Per ulteriori dettagli sul modo migliore per mappare la @ManyToManyrelazione con JPA e Hibernate, consulta questo articolo .