Dies ist eine sehr häufige Frage, daher basiert diese Antwort auf diesem Artikel, den ich in meinem Blog geschrieben habe.
Eins zu viele
Die Eins-zu-Viele-Tabellenbeziehung sieht wie folgt aus:

In einem relationalen Datenbanksystem verknüpft eine Eins-zu-Viele-Tabellenbeziehung zwei Tabellen basierend auf einer Foreign KeySpalte im untergeordneten Element, die Primary Keyauf die der übergeordneten Tabellenzeile verweist .
Im obigen Tabellendiagramm hat die post_idSpalte in der post_commentTabelle eine Foreign KeyBeziehung zur Spalte mit der postTabellen-ID Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
@ManyToOne Annotation
Der beste Weg, um die Eins-zu-Viele-Tabellenbeziehung abzubilden, ist die Verwendung der @ManyToOneAnmerkung.
In unserem Fall PostCommentordnet die post_iduntergeordnete Entität die Spalte @ManyToOneFremdschlüssel mithilfe der Anmerkung zu:
@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;
}
Verwenden der JPA- @OneToManyAnnotation
Nur weil Sie die Option haben, die @OneToManyAnmerkung zu verwenden, bedeutet dies nicht, dass dies die Standardoption für jede Eins-zu-Viele- Datenbankbeziehung sein sollte. Das Problem bei Sammlungen ist, dass wir sie nur verwenden können, wenn die Anzahl der untergeordneten Datensätze eher begrenzt ist.
Der beste Weg, eine @OneToManyZuordnung zuzuordnen , besteht darin, sich auf die @ManyToOneSeite zu verlassen, um alle Änderungen des Entitätsstatus zu verbreiten:
@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);
}
}
Die übergeordnete Entität verfügt Postüber zwei Dienstprogrammmethoden (z. B. addCommentund removeComment), mit denen beide Seiten der bidirektionalen Zuordnung synchronisiert werden. Sie sollten diese Methoden immer bereitstellen, wenn Sie mit einer bidirektionalen Zuordnung arbeiten, da Sie sonst sehr subtile Probleme bei der Zustandsausbreitung riskieren .
Die unidirektionale @OneToManyZuordnung ist zu vermeiden, da sie weniger effizient ist als die Verwendung @ManyToOneoder die bidirektionale @OneToManyZuordnung.
Weitere Informationen zur besten Zuordnung der @OneToManyBeziehung zu JPA und Hibernate finden Sie in diesem Artikel .
Eins zu eins
Die Eins-zu-Eins-Tabellenbeziehung sieht wie folgt aus:

In einem relationalen Datenbanksystem verknüpft eine Eins-zu-Eins-Tabellenbeziehung zwei Tabellen basierend auf einer Primary KeySpalte im untergeordneten Foreign KeyElement, die auch Primary Keyauf die übergeordnete Tabellenzeile verweist .
Daher können wir sagen, dass die untergeordnete Tabelle die Primary Keymit der übergeordneten Tabelle teilt .
Im obigen Tabellendiagramm hat die idSpalte in der post_detailsTabelle auch eine Foreign KeyBeziehung zur postTabellenspalte id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Verwenden der JPA @OneToOnemit @MapsIdAnmerkungen
Der beste Weg, eine @OneToOneBeziehung abzubilden, ist die Verwendung @MapsId. Auf diese Weise benötigen Sie nicht einmal eine bidirektionale Zuordnung, da Sie die PostDetailsEntität jederzeit mithilfe der PostEntitätskennung abrufen können.
Das Mapping sieht folgendermaßen aus:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") öffentliche Klasse PostDetails {
@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
} [/ code]
Auf diese Weise iddient die Eigenschaft sowohl als Primärschlüssel als auch als Fremdschlüssel. Sie werden feststellen, dass in der @IdSpalte keine @GeneratedValueAnmerkung mehr verwendet wird, da der Bezeichner mit dem Bezeichner der postZuordnung gefüllt ist .
Weitere Informationen zur besten Zuordnung der @OneToOneBeziehung zu JPA und Hibernate finden Sie in diesem Artikel .
Viel zu viel
Die Viele-zu-Viele-Tabellenbeziehung sieht wie folgt aus:

In einem relationalen Datenbanksystem verknüpft eine Viele-zu-Viele-Tabellenbeziehung zwei übergeordnete Tabellen über eine untergeordnete Tabelle, die zwei Foreign KeySpalten enthält , die auf die Primary KeySpalten der beiden übergeordneten Tabellen verweisen .
Im obigen Tabellendiagramm hat die post_idSpalte in der post_tagTabelle auch eine Foreign KeyBeziehung zur postTabellen-ID- Primary KeySpalte:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Die tag_idSpalte in der post_tagTabelle hat eine Foreign KeyBeziehung zur Spalte mit der tagTabellen-ID Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Verwenden der JPA- @ManyToManyZuordnung
So können Sie die many-to-manyTabellenbeziehung mit JPA und Hibernate zuordnen:
@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);
}
}
- Die
tagsZuordnung in der PostEntität definiert nur die Typen PERSISTund MERGEKaskadentypen. Wie in diesem Artikel erläutert , ist der REMOVE Entitätsstatusübergang für eine @ManyToManyJPA-Zuordnung nicht sinnvoll, da er eine Kettenlöschung auslösen könnte, die letztendlich beide Seiten der Zuordnung löschen würde.
- Wie in diesem Artikel erläutert , sind die Dienstprogramme zum Hinzufügen / Entfernen obligatorisch, wenn Sie bidirektionale Zuordnungen verwenden, damit Sie sicherstellen können, dass beide Seiten der Zuordnung synchron sind.
- Die
PostEntität verwendet die Entitätskennung für die Gleichheit, da ihr ein eindeutiger Geschäftsschlüssel fehlt. Wie in diesem Artikel erläutert , können Sie die Entitätskennung für die Gleichheit verwenden, solange Sie sicherstellen, dass sie über alle Entitätsstatusübergänge hinweg konsistent bleibt .
- Die
TagEntität verfügt über einen eindeutigen Geschäftsschlüssel, der mit der @NaturalIdAnnotation für den Ruhezustand gekennzeichnet ist . In diesem Fall ist der eindeutige Geschäftsschlüssel der beste Kandidat für Gleichstellungsprüfungen .
- Das
mappedByAttribut der postsZuordnung in der TagEntität kennzeichnet, dass in dieser bidirektionalen Beziehung die PostEntität die Zuordnung besitzt. Dies ist erforderlich, da nur eine Seite eine Beziehung besitzen kann und Änderungen nur von dieser bestimmten Seite an die Datenbank weitergegeben werden.
- Das
Setist zu bevorzugen, da die Verwendung eines Listwith @ManyToManyweniger effizient ist.
Weitere Informationen zur besten Zuordnung der @ManyToManyBeziehung zu JPA und Hibernate finden Sie in diesem Artikel .