Ich hatte das Problem, dass eins zu eins verzögertes Laden im Ruhezustand nicht funktioniert. Ich habe es bereits gelöst , verstehe aber immer noch nicht richtig , was passiert.
Mein Code ( verzögertes Laden funktioniert hier nicht , wenn ich Person - Adresse abrufe, wird auch abgerufen):
@Entity
public class Person{
@Id
@SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
@Column(name = "id")
private long personID;
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Adress address;
//.. getters, setters
}
@Entity
public class Address {
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person"))
private long personID;
@PrimaryKeyJoinColumn
@OneToOne
private FileInfo person;
}
Aber : Wenn ich hinzufügen , optional=false
in OneToOne Beziehung, verzögertes Laden funktioniert gut !
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;
Frage / Bitte: Erklären Sie mir bitte, wie optional=false
Anmerkungen dazu beitragen , ein verzögertes Laden zu erreichen.
PS Ich habe die Beiträge post1 und post2 gelesen und verstehe, warum OneToOne nicht faul sein kann, aber ich kann optional=false
Magie immer noch nicht verstehen .
same table
also benutze ich die @ OneToOne-Beziehung. Ich habe zwar LAZY fetchType verwendet, aber es scheint nicht zu funktionieren. Wenn ich sageoptional=false
, funktioniert es. Jede Erklärung wird sehr geschätzt.Antworten:
Wenn die Zuordnung optional ist, kann der Ruhezustand nicht feststellen, ob für eine bestimmte Person eine Adresse vorhanden ist, ohne eine Abfrage zu erstellen. Daher kann das Adressfeld nicht mit einem Proxy gefüllt werden, da möglicherweise keine Adresse vorhanden ist, die auf die Person verweist, und es kann nicht mit
null
dieser Adresse gefüllt werden, da möglicherweise eine Adresse vorhanden ist, die auf die Person verweist.Wenn Sie die Zuordnung obligatorisch machen (dh
optional=false
), vertraut sie Ihnen und geht davon aus, dass eine Adresse vorhanden ist, da die Zuordnung obligatorisch ist. Daher wird das Adressfeld direkt mit einem Proxy gefüllt, da bekannt ist, dass eine Adresse auf die Person verweist.quelle
Am einfachsten ist es, eine Eins-zu-Viele-Beziehung vorzutäuschen. Dies funktioniert, da das verzögerte Laden der Sammlung viel einfacher ist als das verzögerte Laden einer einzelnen nullbaren Eigenschaft. Im Allgemeinen ist diese Lösung jedoch sehr unpraktisch, wenn Sie komplexe JPQL / HQL-Abfragen verwenden.
Die andere Möglichkeit besteht darin, die Bytecode-Instrumentierung für die Erstellungszeit zu verwenden. Weitere Informationen finden Sie in der Dokumentation zum Ruhezustand: 19.1.7. Verwenden des verzögerten Abrufs von Eigenschaften. Denken Sie daran, dass Sie in diesem Fall
@LazyToOne(LazyToOneOption.NO_PROXY)
der Eins-zu-Eins-Beziehung Anmerkungen hinzufügen müssen , um sie faul zu machen. Es reicht nicht aus, Fetch auf LAZY zu setzen.Die letzte Lösung besteht darin, die Laufzeit-Bytecode-Instrumentierung zu verwenden. Sie funktioniert jedoch nur für Benutzer, die Hibernate als JPA-Anbieter in einer vollständigen JEE-Umgebung verwenden (in diesem Fall sollte die Einstellung "
hibernate.ejb.use_class_enhancer
" auf "true" den Trick ausführen: Entity Manager-Konfiguration) oder "Hibernate with" verwenden Spring ist für das Weben zur Laufzeit konfiguriert (dies ist auf einigen älteren Anwendungsservern möglicherweise schwer zu erreichen). In diesem Fall@LazyToOne(LazyToOneOption.NO_PROXY)
ist auch eine Anmerkung erforderlich.quelle