I know the above question is very common but I just wanted to know exactly when and How Hibernate is fetching the lazily loaded child records.
below is the sample table structure:
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)
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;
}
}
<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>
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;
}
}
<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>
Below is the code block to fetch the list of employees:
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);
}
Now, Here the Mobile numbers is the child record of Employee which is been loaded by the Hibernate lazily as per the hibernate configuration in Employee.hbm.xml (lazy = true)
In the above code, after printing the employee name I am printing the mobile numbers of that employee by iterating the Set mobiles.
I have checked and found that the iteration of the mobileSet is actually fetching the mobileNumbers. i.e.
for(Mobile mobile : mobileSet) {
System.out.println(mobile.getMobileNumber());
}
SO, How It is happening? Because I am not using any hibernate specific API to fetch the lazily loaded child records. Just Iterating over the set of mobile numbers.
Then how Hibernate is fetching the child records internally? What is the background job that Hibernate is doing while I am iterating over the mobileSet?
Please help in understanding my doubt.
In hibernate lazy loading is triggered whenever a lazy loaded property is accessed and it is still managed by the em. If you would access a lazy loaded property when the entity is detached from the entity manager you would get a org.hibernate.LazyInitializationException
To apply the logic to your example: mobile.getMobileNumber() will trigger the lazy loading in your code. Hibernate will then automaticly issue a query to the database. This works because hibernate instantiates proxy objects for lazy loaded propertys, once you try to access these proxys hibernate tries to load them in from the database. this will work if the object is managed and this will result in forementioned exception if the entity is detached. There is no need at all to use a hibernate API to trigger the lazy loading it just happens automaticly when a lazy configured property is accessed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With