Zunächst einige Klarstellungen zu KLEs Antwort:
Die uneingeschränkte (nullfähige) Eins-zu-Eins-Zuordnung ist die einzige, die ohne Bytecode-Instrumentierung nicht als Proxy verwendet werden kann. Der Grund dafür ist, dass die Eigentümerentität wissen MUSS, ob die Zuordnungseigenschaft ein Proxy-Objekt oder NULL enthalten soll, und dies nicht durch Betrachten der Spalten der Basistabelle feststellen kann, da die Eins-zu-Eins-Zuordnung normalerweise über eine gemeinsam genutzte PK erfolgt muss sowieso eifrig geholt werden, was Proxy sinnlos macht. Hier ist eine detailliertere Erklärung.
Viele-zu-Eins-Assoziationen (und natürlich Eins-zu-Viele) leiden nicht unter diesem Problem. Die Eigentümerentität kann problemlos ihre eigene FK überprüfen (und im Fall von Eins-zu-Viele wird zunächst ein leerer Sammlungsproxy erstellt und bei Bedarf ausgefüllt), sodass die Zuordnung faul sein kann.
Eins-zu-eins durch eins-zu-viele zu ersetzen, ist so gut wie nie eine gute Idee. Sie können es durch eindeutige Viele-zu-Eins-Optionen ersetzen, es gibt jedoch auch andere (möglicherweise bessere) Optionen.
Rob H. hat einen wichtigen Punkt, aber Sie können nicht in der Lage sein , es zu implementieren je nach Modell (zB wenn Sie eine Eins-zu-Eins - Zuordnung ist nullable).
Nun zur ursprünglichen Frage:
A) @ManyToOne(fetch=FetchType.LAZY)
sollte gut funktionieren. Sind Sie sicher, dass es in der Abfrage selbst nicht überschrieben wird? Es ist möglich, join fetch
in HQL anzugeben und / oder den Abrufmodus explizit über die Kriterien-API festzulegen, die Vorrang vor Klassenanmerkungen hat. Wenn dies nicht der Fall ist und Sie immer noch Probleme haben, veröffentlichen Sie bitte Ihre Klassen, Abfragen und das daraus resultierende SQL, um eine genauere Konversation zu erhalten.
B) @OneToOne
ist schwieriger. Wenn es definitiv nicht nullbar ist, folgen Sie dem Vorschlag von Rob H. und geben Sie ihn als solchen an:
@OneToOne(optional = false, fetch = FetchType.LAZY)
Wenn Sie andernfalls Ihre Datenbank ändern können (fügen Sie der Besitzertabelle eine Fremdschlüsselspalte hinzu), tun Sie dies und ordnen Sie sie als "verbunden" zu:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
und in OtherEntity:
@OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
Wenn Sie das nicht können (und nicht mit eifrigem Abrufen leben können), ist die Bytecode-Instrumentierung Ihre einzige Option. Ich muss CPerkins jedoch zustimmen - wenn Sie 80 haben !!! tritt aufgrund eifriger OneToOne-Assoziationen bei, Sie haben größere Probleme als diese :-)
one-to-one
mit einer Formel wieselect other_entity.id from other_entity where id = other_entity.id
. Dies ist natürlich nicht ideal für Abfrageleistungen.Damit das verzögerte Laden mit nullbaren Eins-zu-Eins-Zuordnungen funktioniert , müssen Sie den Ruhezustand die Instrumentierung zur Kompilierungszeit durchführen lassen und
@LazyToOne(value = LazyToOneOption.NO_PROXY)
der Eins-zu-Eins-Beziehung ein hinzufügen .Beispielzuordnung:
Beispiel für eine Ant Build-Dateierweiterung (für die Instrumentierung der Kompilierungszeit im Ruhezustand):
quelle
LazyToOneOption.NO_PROXY
und nichtLazyToOneOption.PROXY
?Die Grundidee der XToOnes im Ruhezustand ist, dass sie in den meisten Fällen nicht faul sind.
Ein Grund dafür ist, dass Hibernate, wenn es sich entscheiden muss, einen Proxy (mit der ID) oder eine Null zu setzen,
ohnehin in die andere Tabelle schauen muss, um Mitglied zu werden. Die Kosten für den Zugriff auf die andere Tabelle in der Datenbank sind erheblich. Daher können die Daten für diese Tabelle zu diesem Zeitpunkt abgerufen werden (nicht verzögertes Verhalten), anstatt sie in einer späteren Anforderung abzurufen, für die ein zweiter Zugriff auf die erforderlich wäre gleiche Tabelle.
Bearbeitet: Einzelheiten finden Sie in der Antwort von ChssPly76 . Dieser ist weniger genau und detailliert, er hat nichts zu bieten. Danke ChssPly76.
quelle
Hier ist etwas, das für mich funktioniert hat (ohne Instrumentierung):
Anstatt
@OneToOne
auf beiden Seiten zu verwenden, verwende ich@OneToMany
im umgekehrten Teil der Beziehung (der mitmappedBy
). Das macht die Eigenschaft zu einer Sammlung (List
im folgenden Beispiel), aber ich übersetze sie in ein Element im Getter, um sie für die Clients transparent zu machen.Dieses Setup funktioniert träge, dh die Auswahl erfolgt nur, wenn
getPrevious()
odergetNext()
aufgerufen wird - und nur eine Auswahl für jeden Anruf.Die Tabellenstruktur:
Die Klasse:
quelle
Wie in diesem Artikel erläutert , können Sie die übergeordnete Zuordnung nur dann träge abrufen , wenn Sie die Bytecode-Verbesserung verwenden
@OneToOne
.In den meisten Fällen benötigen Sie jedoch nicht einmal die übergeordnete Zuordnung, wenn Sie sie
@MapsId
auf der Clientseite verwenden:Mit dient
@MapsId
dieid
Eigenschaft in der untergeordneten Tabelle sowohl als Primärschlüssel als auch als Fremdschlüssel für den Primärschlüssel der übergeordneten Tabelle.Wenn Sie also einen Verweis auf die übergeordnete
Post
Entität haben, können Sie die untergeordnete Entität mithilfe der übergeordneten Entitätskennung einfach abrufen:Auf diese Weise treten keine N + 1-Abfrageprobleme auf , die durch die
mappedBy
@OneToOne
Zuordnung auf der übergeordneten Seite verursacht werden könnten .quelle
In nativen XML-Zuordnungen im Ruhezustand können Sie dies erreichen, indem Sie eine Eins-zu-Eins- Zuordnung mit dem eingeschränkten Attribut true deklarieren . Ich bin mir nicht sicher, was das Äquivalent der Hibernate / JPA-Annotation dazu ist, und eine schnelle Suche im Dokument lieferte keine Antwort, aber hoffentlich gibt Ihnen dies einen Anhaltspunkt, um fortzufahren.
quelle
@OneToOne(optional=false,fetch=FetchMode.LAZY)
Wie bereits perfekt durch ChssPly76, Hibernate erklärt Proxies nicht helfen , mit unbeschränkten (nullable) eine Eins-zu-Eins - Verbände, aber es gibt einen Trick erklärt hier zu vermeiden Instrumentierung einzurichten. Die Idee ist, Hibernate zu täuschen, dass die Entitätsklasse, die wir verwenden möchten, bereits instrumentiert wurde: Sie instrumentieren sie manuell im Quellcode. Es ist einfach! Ich habe es mit CGLib als Bytecode-Anbieter implementiert und es funktioniert (stellen Sie sicher, dass Sie in Ihrem HBM lazy = "no-proxy" und fetch = "select" konfigurieren, nicht "join").
Ich denke, dies ist eine gute Alternative zur echten (ich meine automatischen) Instrumentierung, wenn Sie nur eine Eins-zu-Eins-Null-Beziehung haben, die Sie faul machen möchten. Der Hauptnachteil besteht darin, dass die Lösung von dem von Ihnen verwendeten Bytecode-Anbieter abhängt. Kommentieren Sie Ihre Klasse daher genau, da Sie den Bytecode-Anbieter möglicherweise in Zukunft ändern müssen. Natürlich modifizieren Sie Ihre Modellbohne auch aus technischen Gründen, und das ist nicht in Ordnung.
quelle
Diese Frage ist ziemlich alt, aber mit Hibernate 5.1.10 gibt es einige neue, komfortablere Lösungen.
Das verzögerte Laden funktioniert mit Ausnahme der übergeordneten Seite einer @ OneToOne-Zuordnung. Dies liegt daran, dass der Ruhezustand keine andere Möglichkeit hat, zu wissen, ob dieser Variablen eine Null oder ein Proxy zugewiesen werden soll. Weitere Details finden Sie in diesem Artikel
quelle
Wenn die Beziehung nicht bidirektional sein darf, ist eine @ ElementCollection möglicherweise einfacher als die Verwendung einer faulen One2Many-Sammlung.
quelle