Hier ist, was ich versuche zu tun.
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%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:
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.
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.
Sie können versuchen, eine Ansicht in Ihrer Datenbank zu konfigurieren, die diese Eins-zu-eins-Beziehung widerspiegelt.
[Dieser Teil hält nicht mehr]
Ändere dies in deinem Parent
wie unten,
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,
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.