Wie Lazy loading von untergeordneten Datensätzen funktioniert in Hibernate?
Ich weiß, die obige Frage ist sehr allgemein, aber ich wollte nur wissen, Wann genau und Wie Hibernate ist das abrufen der träge geladen untergeordneten Datensätze.
unten ist der Beispiel-Tabelle Struktur:
Tisch Struktur:
employee_table(e_id, e_name, e_sal)
(100, XYZ, 20000)
mobile_table(m_id, m_number, e_id)
(1, 8728271817, 100)
(2, 0983813919, 100)
Employee.java
public class Employee implements Serializable {
private static final long serialVersionUID = 1930751473454928876L;
private long employeeId;
private String employeeName;
private double employeeSal;
private Set<Mobile> mobiles;
public long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(long employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public double getEmployeeSal() {
return employeeSal;
}
public void setEmployeeSal(double employeeSal) {
this.employeeSal = employeeSal;
}
public Set<Mobile> getMobiles() {
return mobiles;
}
public void setMobiles(Set<Mobile> mobiles) {
this.mobiles = mobiles;
}
}
Employee.hbm.xml
<hibernate-mapping>
<class name="edu.sandip.hibernate.Employee" table="EMPLOYEE_T">
<id name="employeeId" column="e_id" type="long">
<generator class="increment" />
</id>
<property name="employeeName" column="e_name" type="string" />
<property name="employeeSal" column="e_sal" type="double" />
<set name="mobiles" table="MOBILE_T" inverse="true" lazy="true" fetch="select" >
<key>
<column name="e_id" not-null="true" />
</key>
<one-to-many class="edu.sandip.hibernate.Mobile" />
</set>
</class>
</hibernate-mapping>
Mobile.java
public class Mobile implements Serializable {
private static final long serialVersionUID = 6279006639448045512L;
private long mobId;
private String mobileNumber;
private Employee employee;
public long getMobId() {
return mobId;
}
public void setMobId(long mobId) {
this.mobId = mobId;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((mobileNumber == null) ? 0 : mobileNumber.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Mobile other = (Mobile) obj;
if (mobileNumber == null) {
if (other.mobileNumber != null)
return false;
} else if (!mobileNumber.equals(other.mobileNumber))
return false;
return true;
}
}
Mobile.hbm.xml
<hibernate-mapping>
<class name="edu.sandip.hibernate.Mobile" table="MOBILE_T">
<id name="mobId" column="m_id" type="long">
<generator class="increment" />
</id>
<property name="mobileNumber" column="m_number" type="string" />
<many-to-one name="employee" class="edu.sandip.hibernate.Employee" fetch="select">
<column name="e_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
Unten ist der code-block zum abrufen der Liste der Mitarbeiter:
public List<Employee> getAllEmployees() {
List<Employee> list = null;
Session session = null;
try {
session = getSession();
Query query = session.createQuery("FROM Employee");
list = query.list();
for(Employee employee : list) {
System.out.println("Emaployee Name: " + employee.getEmployeeName);
Set<Mobile> mobileSet = employee.getMobiles();
System.out.println("Mobile Numbers: ");
for(Mobile mobile : mobileSet) {
System.out.println(mobile.getMobileNumber());
}
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if(session != null) {
System.out.println("session is still alive");
releaseSession(session);
}
}
return (list);
}
Nun, Hier die Handy-Nummern der untergeordneten Datensatz des Mitarbeiters, die geladen wurden von der Hibernate-faul wie pro die hibernate-Konfiguration in Employee.hbm.xml (lazy = true)
In dem obigen code nach dem drucken der name des Mitarbeiters ich bin drucken des mobile-Nummern, die
Mitarbeiter durch Durchlaufen der Set-Handys.
Habe ich überprüft und festgestellt, dass die iteration des mobileSet ist eigentlich das abrufen der mobileNumbers.
also
for(Mobile mobile : mobileSet) {
System.out.println(mobile.getMobileNumber());
}
SO, Wie Es passiert ist? Weil ich bin nicht mit jedem hibernate-spezifische API zu Holen, die verzögert geladen untergeordneten Datensätze. Nur die Iteration über der Menge der Handy-Nummern.
Dann wie Hibernate ist das abrufen der untergeordneten Datensätze intern? Was ist der hintergrund-job, der Winterschlaf ist zu tun, während ich bin iteriert mobileSet?
Bitte helfen Sie verstehen meine Zweifel.
InformationsquelleAutor Sandy | 2014-03-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
In hibernate lazy loading wird ausgelöst, wenn eine lazy-loaded-Eigenschaft zugegriffen wird, und es ist noch geschafft von der em. Wenn Sie Zugriff auf eine lazy-Eigenschaft geladen, wenn die Entität ist, losgelöst von der entity-manager, den Sie bekommen würde, eine org.hibernate.LazyInitializationException
Zur Anwendung der Logik zu Ihrem Beispiel:
mobile.getMobileNumber() löst die lazy loading in Ihrem code. Hibernate wird dann automatisch eine Abfrage an die Datenbank. Dies funktioniert, da hibernate erzeugt proxy-Objekte für die lazy geladen propertys, sobald Sie versuchen, Zugang zu diesen proxys hibernate versucht, Sie zu laden in der Datenbank. dies funktioniert, wenn das Objekt verwaltet und dadurch wird diese Ausnahme ausgelöst, wenn die Einheit getrennt ist. Es gibt überhaupt keine Notwendigkeit zur Verwendung einer hibernate-API zum auslösen der lazy loading es passiert einfach automatisch, wenn ein fauler konfiguriert Eigenschaft zugegriffen
Ich bearbeitet meine Antwort auf anwenden, um die Erklärung zu deinem Beispiel
InformationsquelleAutor steelshark
In Ihrem Employee.hbm.xml die Datei, die Sie angegeben haben, dass die fetch-Strategie für Mobile faul ist.
Das sagt hibernate generieren, die eine einfache SQL-Anweisung, um die Tabelle entspricht, um Mitarbeiter ohne jegliche Verknüpfungen mit den entsprechenden Mobilen Tisch.
Jedoch, wenn Mitarbeiter.getMobiles() aufgerufen wird,
Hibernate wird eine select-Abfrage auf die letztere Tabelle mit einer where-Klausel mit der primary-key der früheren Tabelle.
Den Weg, die Holen implementiert ist, führt hier zu dem berüchtigten N+1 problem
Wenn träge geladene Objekte vorhanden sind, in ein Unternehmen, Hibernate verwendet einen proxy (erstellt mit Javassist) , steht an der Stelle der träge geladene Objekt. Wenn das Objekt abgerufen wird (über getMobiles() in diesem Beispiel) und das Objekt ist immer noch im Status "verwaltet", dann kann der proxy-Trigger eine neue select-Abfrage an die Datenbank. Wenn das Objekt nicht geschafft, dann bekommen Sie die gefürchtete LazyInitializationException. Ich schlage vor, Sie Lesen den Java-Persistenz mit Hibernate für die details
InformationsquelleAutor geoand
Diesem Thema könnte Ihnen helfen, zu verstehen, was ist der trick hinter lazy loading :
Wie proxy lädt die lazy-Eigenschaft in Hibernate/JPA
InformationsquelleAutor Maxime B.