2012-06-10 9 views
5

zu definieren, was genau ist der Unterschied in den beiden folgenden ErklärungenJPA - Unterschied in der Nutzung der mappedBy Eigenschaft die besitzende Einheit

B ist die besitzende Seite

@Entity 
class A { 
    @Id int id; 

    @OneToOne 
    B b; 
} 

@Entity 
class B { 
    @Id int id; 

    @OneToOne(mappedBy="b") 
    A a; 
} 

A ist die besitzende Seite

Wenn ich dies in "normalem SQL" denke, denke ich, dass es dasselbe ist wie zwei Tabellen, die jeweils den Fremdschlüssel der anderen Tabelle haben. Was ich jedoch nicht verstehe, ist die Auswirkung der Angabe, welche Entität die besitzende Seite ist, d. H. Die Eigenschaft 'mappedBy'. Was erreicht das eigentlich, da ich nicht glaube, dass es im normalen SQL ein Äquivalent gibt?

+2

Haben Sie überprüft, ob in beiden Fällen die Tabellen A und B miteinander übereinstimmen? –

Antwort

10

Die JPA 2.0 specification, Abschnitt 2.9, schreibt:

Beziehungen bidirektional oder unidirektional sein können. Eine bidirektionale Beziehung hat sowohl eine besitzende als auch eine inverse (nicht besitzende) Seite. Eine unidirektionale Beziehung hat nur eine besitzende Seite. Die besitzende Seite einer Beziehung bestimmt die Aktualisierungen der Beziehung in der Datenbank, wie in Abschnitt 3.2.4 beschrieben.

Die folgenden Regeln gelten für bidirektionale Beziehungen:

  • Die inverse Seite einer bidirektionalen Beziehung zu seinem Besitz Seite durch die Verwendung des mappedBy Elements der OneToOne, OneToMany oder ManyToMany Anmerkung verweisen. Das Element mappedBy bezeichnet die Eigenschaft oder das Feld in der Entität, die der Eigentümer der Beziehung ist.
  • Die vielen Seiten von Eins-zu-Viele/Viele-zu-Eins-bidirektionale Beziehungen müssen die Eigentümerseite sein, daher kann das mappedBy-Element nicht in der ManyToOne-Annotation angegeben werden.
  • Für 1: 1-bidirektionale Beziehungen entspricht die besitzende Seite der Seite, die den entsprechenden Fremdschlüssel enthält.
  • Für Viele-zu-viele bidirektionale Beziehungen kann jede Seite die besitzende Seite sein.

Die relevanten Teile von Abschnitt 3.2.4 sind:

Der Zustand des persistenten Entitäten in die Datenbank in Transaktionscommit synchronisiert ist. Diese Synchronisation beinhaltet das Schreiben von Updates für persistente Entitäten und deren Beziehungen, wie oben angegeben.

und

bidirektionale Beziehungen zwischen verwalteten Einheiten werden von der besitzenden Seite der Beziehung gehalten basierend auf Referenzen beibehalten werden. Es liegt in der Verantwortung des Entwicklers, dass die auf der besitzenden Seite gehaltenen und die auf der inversen Seite gespeicherten Referenzen im Speicher bei jeder Änderung konsistent bleiben. Bei unidirektionalen Eins-zu-Eins und Eins-zu-Viele-Beziehungen ist es Aufgabe des Entwicklers sicherzustellen, dass die Semantik der Beziehungen eingehalten wird.

Es ist besonders wichtig, dass Änderungen an der inversen Seite einer Beziehung Ergebnis in entsprechendem Updates auf der besitzenden Seite zu gewährleisten, um die Änderungen zu gewährleisten, nicht verloren gehen, wenn sie in die Datenbank synchronisiert werden.

+1

+1 für die Verweise auf die Spezifikation. –

+0

Ich denke, das schließt alle anderen Antworten ab :-) +1 – siebz0r

4

Im ersten Beispiel die A Tabelle haben wird 2 Spalten id und b_id, die B Tabelle eine Spalte, id haben wird. Dies macht A die besitzende Seite.

Im zweiten Beispiel ist B die besitzende Seite. B hat zwei Spalten, id und a_id. A wird eine Spalte haben, id.

Und das ist der Unterschied :-)

3

Die besitzende Seite ist die Seite, die JPA zu wissen, betrachtet ist der Verein existiert oder nicht. Angenommen, Sie gehen mit Ihrem ersten Beispiel. Die besitzende Seite ist die Seite, auf der es kein mappedBy-Attribut gibt. Die besitzende Seite ist also A und nicht B.

Das bedeutet, dass, wenn Sie ein A und ein B in der Datenbank haben, und Sie tun

A a = em.find(A.class, aId); 
B b = em.find(B.class, bId); 
a.setB(b); 

JPA den Verein retten (dh es wird die Speicherung ID von B in der Join-Spalte von Tabelle A).

Aber wenn Sie

A a = em.find(A.class, aId); 
B b = em.find(B.class, bId); 
b.setA(a); 

nichts tun, wird in der Datenbank geändert werden, da Sie die inverse Seite geändert und vergessen haben, die besitzende Seite zu ändern.

6

Wie andere haben darauf hingewiesen, Sie sind falsch, welche Seite die besitzende Seite in Ihre Beispiele. Mit besitzende Seite meinen wir, die Beziehung von einer OO-Perspektive zu besitzen, die in der Praxis oft das Gegenteil davon ist, wie es in der db erzeugt wird oder erzeugt wird, wenn man einen rdbm als Persistenzanbieter verwendet.

Unter normalen Umständen macht das OO-Modell ziemlich klar, welche Seiten die besitzende Seite ist. Zum Beispiel hat eine Bestellung OrderLines. Wenn wir eine Bestellung löschen, sollten alle Bestellzeilen gelöscht werden. Wenn wir eine OrderLine löschen, hat der Auftrag möglicherweise noch ein Existenzrecht. Daher ist der Orden die besitzende Seite.

Für ein konkreteres und exzellentes Beispiel, auf die Auswirkungen davon, welche Seite die besitzende Seite ist, beziehe ich mich auf @JB Nizet Antwort.

Gemäß Abschnitt 2.9 der JPA 2.0 spec:

Für eine Eins-zu-Eins-Beziehungen bidirektionale entsprechen die besitzenden Seiten auf die Seite, die den entsprechenden Fremdschlüssel enthält.

Aber im selben Abschnitt haben wir auch:

Darüber hinaus ist diese Spezifikation erfordert auch die Unterstützung für die Strategien alternative Abbildung folgt vor: [..] Die Abbildung von uni- und bidirektionalen Ein- Zu-eins-Beziehungen, bidirektionale Viele-zu-Eins/Eins-zu-Viele-Beziehungen und unidirektionale Viele-zu-Eins-Beziehungen mittels Join-Tabelle Zuordnungen.

Etwas weitere nach unten in dem gleichen Abschnitt mit ihm weiter:

Zusätzliche Abbildungs ​​Annotationen (zB Spalte und Tabellenzuordnung Annotationen) können außer Kraft setzen oder weiter verfeinern die Standard Spezi- fied werden Zuordnungen und Zuordnungsstrategien, die in Abschnitt 2.10 beschrieben sind. Einige Implementierungen machen sich das zunutze, um den FK eines bidirektionalen OneToOne in der Zieltabelle zu haben.

einige über einige Strategien zu lesen, das Szenario zu lösen, finden Sie unter: An almost good explaination

ich nicht überprüft haben, aber ich hoffe und glaube, dass 2.1 das erste Angebot entfernen. Da die tatsächliche Datenbankstruktur so wenig wie möglich darauf beschränkt sein sollte, wie wir Daten als Entitäten modellieren können.

+0

Nein, JPA gibt an, dass die besitzende Seite einer OneToOne bidirektionalen Assoziation diejenige ist, die den Fremdschlüssel enthält. Gleiches gilt für bidirektionale OneToMany. –

+0

"und es kann in einer OneToOne-Zuordnung verwendet werden, in der der Primärschlüssel der referenzierenden Entität als Fremdschlüssel für die referenzierte Entität verwendet wird." http://docs.oracle.com/javaee/6/api/javax/persistence/PrimaryKeyJoinColumn.html. Die Situation _just_ erscheint nicht so oft. – esej

+0

Und das ändert nichts. In diesem Fall ist die Primärschlüsselspalte die Join-Spalte (daher der Name PrimaryKeyJoinColumn) und die Entität, die diese Annotation und somit die Join-Spalte enthält, ist die Eigentümerseite. Lesen Sie die @ meriton-Antwort, die diesen Auszug aus der JPA-Spezifikation enthält: "Bei einseitigen bidirektionalen Beziehungen entspricht die besitzende Seite der Seite, die den entsprechenden Fremdschlüssel enthält." –

Verwandte Themen