9 Stimmen

Warum wird in der Hibernate-Dokumentation empfohlen, eine Join-Tabelle für eine One-to-Many-Beziehung zu verwenden?

Ich dachte, dass die übliche Art und Weise, eine eins-zu-viele-Beziehung in einer Datenbank zu modellieren, über eine Fremdschlüsselbeziehung erfolgt (d.h. ein Kunde mit vielen Bestellungen -> die Tabelle Bestellung erhält einen FK-Verweis auf die Tabelle Kunde).

Hibernate empfiehlt jedoch die Verwendung einer Join-Tabelle zur Modellierung solcher Beziehungen:

Ein unidirektionales one to many unter Verwendung einer Fremdschlüsselspalte in der eigenen Entität ist nicht üblich und wird nicht wirklich empfohlen. Wir raten raten Ihnen dringend, eine Join-Tabelle für diese Art von Assoziation zu verwenden (wie im nächsten Abschnitt erklärt). Diese Art der Verknüpfung wird beschrieben durch eine @JoinColumn beschrieben.

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association

Warum ist dies "nicht wirklich empfehlenswert". Ich dachte, die Verwendung einer FK sei der Standard, und Join-Tabellen würden nur für Many-to-Many-Beziehungen verwendet?

Ich erstelle ungern eine Verknüpfungstabelle, weil das Datenmodell dann so aussieht, als ob es sich um eine Many-to-many-Beziehung handelt, obwohl es sich in Wirklichkeit um eine One-to-many-Beziehung handelt.

Was ist der Grund für diese Empfehlung in den Hibernate-Dokumenten?

5voto

atrain Punkte 9035

Diese Frage wurde bereits in den Hibernate-Foren gestellt und beantwortet: https://forum.hibernate.org/viewtopic.php?t=954178&highlight=unidirectional+Null+Fürsorge+Ausland+Schlüssel . Es scheint weniger ein Problem des DB-Designs zu sein als vielmehr eines der Funktionsweise von Hibernate.

3voto

GeorgeG Punkte 248

Das Zitat aus der von Ihnen geposteten Dokumentation beschreibt eine unidirektional @OneToMany-Assoziation, was eine andere Sache ist. In einer solchen Assoziation gibt es nur einen Verweis von Customer auf Orders, nicht umgekehrt. Die Abbildung dieser Art von Assoziation sollte also mit einer Join-Tabelle erfolgen, die die Sammlung von Bestellungen für jeden Kunden enthält.

Ich vermute, dass die Assoziation, an die Sie denken, eher eine @ManyToOne-Assoziation ist, bei der der Verweis von Order auf Customer erfolgt.

Beachten Sie, dass Sie, wenn Sie eine bidirektionale Assoziation modellieren möchten, das Attribut "mappedBy" in der @OneToMany-Annotation verwenden können.

2voto

Ryan Stewart Punkte 120600

Ich kann nicht mit Bestimmtheit sagen, was ich denke, aber ich war immer der Meinung, dass mit unidirektional Beziehungen, ist die Wahrscheinlichkeit höher, dass Ihr Orden am Ende mehrerer solcher Beziehungen steht. Damit steigt auch die Wahrscheinlichkeit, dass die Bestellung in einigen dieser Spalten Nullen enthält, weil die Bestellung zwar erstellt wurde, aber andere Objekte, die auf die Bestellung verweisen können, entweder noch nicht existieren oder nie existieren werden. Aus diesem Grund ist es eine Frage der Normalisierung, die FK-Spalten in eine andere Tabelle zu verschieben. Hinzu kommt die Tatsache, dass die Objektbeziehungen besser widergespiegelt werden. Bei einer unidirektionalen eins-zu-eins-Beziehung von Foo -> Bar würde man erwarten, dass die FK in Foo und nicht in Bar zu finden ist, da die Eigentümerschaft im Objektmodell dort liegt. Das Gleiche gilt für eine uni-one-to-many von Customer -> Order. Wenn man sich das Objektmodell ansieht, erwartet man nicht, dass die Eigentümerschaft in der Bestellung dargestellt wird, also auch nicht in der Tabelle Bestellung.

2voto

bwtaylor Punkte 384

Der vorherige Abschnitt in der Hibernate-Dokumentation behandelt bidirektionale One-to-many-Beziehungen und beschreibt, was Sie wahrscheinlich gewohnt sind, mit einem Standard-Fremdschlüssel auf der Many-Entität. Wie bereits gesagt wurde, ist diese Antwort nur dann angemessen, wenn Sie ausdrücklich eine unidirektionale Beziehung wünschen.

Unidirektionalität ist nur dann erwünscht, wenn die Many-Seite nichts von der Beziehung wissen darf. Das bedeutet, dass die Klasse auf der Many-Seite kein Attribut haben kann, um die Beziehung darzustellen, fast per Definition. Betrachten Sie dieses Problem also als die Frage: "Wie kann ich eine Eins-zu-Viel-Beziehung darstellen, ohne den normalen Ansatz zu verwenden".

Eine unidirektionale Beziehung wie diese ist sicherlich etwas ungewöhnlich, aber ich kann mir Situationen vorstellen, in denen Sie dies aus Gründen der Entkopplung, Sicherheit, Prüfung oder Unveränderbarkeit wünschen. Nehmen wir zum Beispiel an, Sie modellieren eine klinische Studie, und Ihre Klassen sind Patient und Medikament, und während der Studie geben Sie jedem Patienten eines von mehreren Medikamenten. Sie möchten, dass jede Logik, die mit dem Patienten arbeitet, vollständig davon entkoppelt ist, welches Medikament ihm zugewiesen wird. Anstatt also patient.setMedication() zu verwenden, wie Sie es normalerweise tun würden, erstellen Sie die Join-Klasse MedicationPatientMap und rufen medication.getMedicationPatientMap().addPatient(patient) auf. Dann können Sie den Zugriff auf die Eins-zu-Viel-Beziehung zwischen Medikament und Patient mit Logik auf der Medikamentenseite steuern.

Ich glaube nicht, dass die Kundenbestellung ein gutes Beispiel dafür ist, denn normalerweise erwartet unser mentales Modell von Bestellungen, dass die Kunden von dort aus erreichbar sind. Und wirklich, die meiste Zeit sind Sie nicht

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X