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 Key
Spalte im untergeordneten Element, die Primary Key
auf die der übergeordneten Tabellenzeile verweist .
Im obigen Tabellendiagramm hat die post_id
Spalte in der post_comment
Tabelle eine Foreign Key
Beziehung zur Spalte mit der post
Tabellen-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 @ManyToOne
Anmerkung.
In unserem Fall PostComment
ordnet die post_id
untergeordnete Entität die Spalte @ManyToOne
Fremdschlü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- @OneToMany
Annotation
Nur weil Sie die Option haben, die @OneToMany
Anmerkung 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 @OneToMany
Zuordnung zuzuordnen , besteht darin, sich auf die @ManyToOne
Seite 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. addComment
und 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 @OneToMany
Zuordnung ist zu vermeiden, da sie weniger effizient ist als die Verwendung @ManyToOne
oder die bidirektionale @OneToMany
Zuordnung.
Weitere Informationen zur besten Zuordnung der @OneToMany
Beziehung 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 Key
Spalte im untergeordneten Foreign Key
Element, die auch Primary Key
auf die übergeordnete Tabellenzeile verweist .
Daher können wir sagen, dass die untergeordnete Tabelle die Primary Key
mit der übergeordneten Tabelle teilt .
Im obigen Tabellendiagramm hat die id
Spalte in der post_details
Tabelle auch eine Foreign Key
Beziehung zur post
Tabellenspalte id
Primary Key
:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Verwenden der JPA @OneToOne
mit @MapsId
Anmerkungen
Der beste Weg, eine @OneToOne
Beziehung abzubilden, ist die Verwendung @MapsId
. Auf diese Weise benötigen Sie nicht einmal eine bidirektionale Zuordnung, da Sie die PostDetails
Entität jederzeit mithilfe der Post
Entitä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 id
dient die Eigenschaft sowohl als Primärschlüssel als auch als Fremdschlüssel. Sie werden feststellen, dass in der @Id
Spalte keine @GeneratedValue
Anmerkung mehr verwendet wird, da der Bezeichner mit dem Bezeichner der post
Zuordnung gefüllt ist .
Weitere Informationen zur besten Zuordnung der @OneToOne
Beziehung 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 Key
Spalten enthält , die auf die Primary Key
Spalten der beiden übergeordneten Tabellen verweisen .
Im obigen Tabellendiagramm hat die post_id
Spalte in der post_tag
Tabelle auch eine Foreign Key
Beziehung zur post
Tabellen-ID- Primary Key
Spalte:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Die tag_id
Spalte in der post_tag
Tabelle hat eine Foreign Key
Beziehung zur Spalte mit der tag
Tabellen-ID Primary Key
:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Verwenden der JPA- @ManyToMany
Zuordnung
So können Sie die many-to-many
Tabellenbeziehung 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
tags
Zuordnung in der Post
Entität definiert nur die Typen PERSIST
und MERGE
Kaskadentypen. Wie in diesem Artikel erläutert , ist der REMOVE
Entitätsstatusübergang für eine @ManyToMany
JPA-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
Post
Entitä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
Tag
Entität verfügt über einen eindeutigen Geschäftsschlüssel, der mit der @NaturalId
Annotation für den Ruhezustand gekennzeichnet ist . In diesem Fall ist der eindeutige Geschäftsschlüssel der beste Kandidat für Gleichstellungsprüfungen .
- Das
mappedBy
Attribut der posts
Zuordnung in der Tag
Entität kennzeichnet, dass in dieser bidirektionalen Beziehung die Post
Entitä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
Set
ist zu bevorzugen, da die Verwendung eines List
with @ManyToMany
weniger effizient ist.
Weitere Informationen zur besten Zuordnung der @ManyToMany
Beziehung zu JPA und Hibernate finden Sie in diesem Artikel .