Eager and Lazy Loading In Hibernate and JPA
Suppose if we have two entities and there is a relationship between them. For example, we might have an entity called User and another entity called Order and a User might have many Orders:
The User entity might have some basic properties such as id, name, address, etc. as well as a collection property called orders that returns the list of orders for a given User
public class User {
private Long userId;
private String username;
private String address;
private Set<Order> order = new HashSet<Order>();
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<Order> getOrder() {
return order;
}
public void setOrder(Set<Order> order) {
this.order = order;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Now when we load a user from the database, JPA loads its id, name, and address fields for you. But we have two options for how the orders should be loaded:
- To load it together with the rest of the fields (i.e. eagerly).
- To load it on-demand (i.e. lazily) when you call users getOrder() method.
When a user has many orders it is not efficient to load all of its orders together with it, especially when they are not needed and in suchlike cases, we can declare that you want orders to be loaded when they are actually needed. This is called lazy loading.
Here's an example, where orders are explicitly marked to be loaded lazily:
package com.knf.eagerlazyfetch.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "USER_ID")
private Long userId;
private String username;
private String userAddress;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<Order> order = new HashSet<Order>();
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<Order> getOrder() {
return order;
}
public void setOrder(Set<Order> order) {
this.order = order;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
}
Here's an example, where orders are explicitly marked to be loaded eagerly:
package com.knf.eagerlazyfetch.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "USER_ID")
private Long userId;
private String username;
private String userAddress;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
private Set<Order> order = new HashSet<Order>();
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<Order> getOrder() {
return order;
}
public void setOrder(Set<Order> order) {
this.order = order;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
}