Hibernate OneToOne Lazy Laden und Kaskadieren

7

Hier ist, was ich versuche zu tun.

  1. Erstellen Sie einen Elternteil mit einer OneToOne-Beziehung zu einem Kind
  2. Der Elternteil muss die Kinder mit Lazy Loading
  3. holen
  4. Wenn das übergeordnete Element entfernt wird, gilt dies auch für das untergeordnete Element
  5. Wenn das Kind entfernt wird, sollte der Elternteil nicht betroffen sein
  6. Das Kaskaden-Update und -Delete muss in DDL
  7. übersetzt werden

Klasse Parent

%Vor%

Klasse Kind

%Vor%

Ich habe Punkt 1, 3, 4 voll funktionsfähig und Punkt 5 teilweise funktioniert, muss noch lösen, wie der Update-Teil indo DDL zu übersetzen.

Punkt 2 ist das große Problem hier, mit meiner aktuellen Lösung lädt das Elternteil das Kind nicht träge. Das Kind lädt jedoch den Elternteil träge, aber das Invertieren der Annotationen würde die Kaskadierung stören ( Punkte 3, 4 und 5 ).

Ich bin gerade sehr verwirrt, in der Hoffnung, etwas Offensichtliches verpasst zu haben, also würde jede Hilfe sehr geschätzt werden.

BEARBEITEN: Von Adeel Ansari angeforderter Code

'fetch = FetchType.LAZY' wurde zur Klasse Parent hinzugefügt, ansonsten wie oben.

%Vor%

Die resultierenden Hibernate-Abfragen, von denen jeweils ein übergeordnetes und ein untergeordnetes untergeordnetes Element abgerufen werden:

%Vor%

Hier ist der Code für findByPrimaryKey:

%Vor%     
Holm 09.06.2011, 08:44
quelle

4 Antworten

20

Ich habe ein ähnliches Problem gehabt. Es gibt ein paar verschiedene Lösungen, aber alle sind Workarounds.

Die kurze Antwort ist: Hibernate unterstützt keine faulen Eins-zu-Eins-Beziehungen.

Die lange Antwort (Workaround) ist:

  1. Deklarieren Sie die Beziehung auf der einen Seite als Eins-zu-Eins (Kind) und auf der anderen Seite als Eins-zu-Viele (Eltern). Ein parent.getchild() gibt also eine Menge zurück, aber es kann Lazy Loading verwenden.

  2. Sie können versuchen, den übergeordneten Schlüssel für den übergeordneten und die untergeordneten Elemente freizugeben. Dazu müssten Sie jedoch das Schema ändern.

  3. Sie können versuchen, eine Ansicht in Ihrer Datenbank zu konfigurieren, die diese Eins-zu-eins-Beziehung widerspiegelt.

iliaden 09.06.2011, 13:33
quelle
11

[Dieser Teil hält nicht mehr]

Ändere dies in deinem Parent wie unten,

%Vor%

Sollte funktionieren.

[Bearbeitet um zu erklären, warum es nicht funktioniert]

  

Direkt nach dem Laden von B können Sie anrufen   getCee (), um C zu erhalten. Aber sieh,   getCee () ist eine Methode Ihrer Klasse und   Hibernate hat keine Kontrolle darüber.   Hibernate weiß nicht, wann jemand   werde getCee () aufrufen. Das bedeutet   Hibernate muss ein entsprechendes setzen   Wert in "cee" Eigentum an der   Moment lädt es B aus der Datenbank.

     

Wenn Proxy für C aktiviert ist, Hibernate   kann ein C-Proxy-Objekt, das nicht ist   geladen, aber wird geladen, wenn   jemand benutzt es. Das gibt faul   Laden für eins zu eins.

     

Aber jetzt stell dir vor, dein B-Objekt könnte oder   möglicherweise nicht zugeordnet C   (eingeschränkt="falsch"). Was sollte   getCee () gibt zurück, wenn B spezifisch ist   nicht C haben? Null. Aber erinnere dich,   Hibernate muss den korrekten Wert von festlegen   "cee" in dem Moment, als es B gesetzt hat (weil   Es weiß nicht, wann jemand anruft   getCee ()). Proxy hilft hier nicht   weil sich Proxy bereits in sich befindet   Nicht-Null-Objekt.

     

Wenn Ihr B- & gt; C-Mapping ist   obligatorisch (eingeschränkt = wahr),   Hibernate verwendet den Proxy für C   was zu einer langsamen Initialisierung führt. Aber   wenn Sie B ohne C zulassen, Hibernate   HAT nur die Anwesenheit von C in der   Moment lädt es B. Aber ein SELECT zu   Überprüfen Sie Anwesenheit ist nur ineffizient   weil die gleiche SELECT nicht nur   Presence prüfen, aber ganze laden   Objekt. So lazy loading geht weg.

Referenz: Ссылка

[Bearbeitet, um eine Problemumgehung hinzuzufügen]

Sie können optional=false und @LazyToOne für die Beziehung verwenden, die nicht optional ist. Vergessen Sie nicht, cascade={CascadeType.PERSIST,CascadeType.REMOVE} einzuschließen. Da ist es offensichtlich für eine nicht-optionale Beziehung. Unten ist ein Beispiel,

%Vor%

Dies sollte für Sie funktionieren, da ich sehe, dass Sie cascade=CascadeType.ALL verwenden, was nicht optional bedeutet. Ist es nicht? Aber für die optionale Beziehung möchten Sie vielleicht die Problemumgehung in iliaden hier berücksichtigen.

    
Adeel Ansari 09.06.2011 09:00
quelle
7

Hast du @OneToOne(fetch = FetchType.LAZY, optional=false) ausprobiert? Überprüfen Sie auch diesen Blog und dieser Thread.

    
abalogh 09.06.2011 09:01
quelle
0

@ Eins-zu-eins-Beziehung unterstützt keine faule Initialisierung . Um das Objekt abzurufen, setze nicht FetchType.LAZY in die untergeordnete Klasse und erhalte alle untergeordneten Objekte.

%Vor%     
borchvm 16.04.2014 08:53
quelle

Tags und Links