Abstract:
As we known, there are 3 kinds of fetch strategy in Hibernate. They are “join”,”select” and “subselect”.
In this article, I took an example with Customer and Order Entities to show you what is the different between these fetch strategies.
Hope it will useful for you. BTW, this is not a final version. I will follow up it in future.
package net.sampledb.model;
import java.util.HashSet;
import java.util.Set;
/**
* Customers entity.
*
* @author Xianyi.Ye
*/
public class Customer implements java.io.Serializable {
// Fields
private Long id;
private Integer version;
private String name;
private String password;
private String email;
private Set orders = new HashSet(0);
// Constructors
/** default constructor */
public Customer() {
}
/** minimal constructor */
public Customer(Integer version, String name) {
this.version = version;
this.name = name;
}
/** full constructor */
public Customer(Integer version, String name, String password,
String email, Set orders) {
this.version = version;
this.name = name;
this.password = password;
this.email = email;
this.orders = orders;
}
// Property accessors
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public Set getOrders() {
return orders;
}
public void setOrders(Set orders) {
this.orders = orders;
}
}
package net.sampledb.model;
import java.util.HashSet;
import java.util.Set;
/**
* Orders entity.
*
* @author Xianyi.Ye
*/
public class SampleOrder implements java.io.Serializable {
// Fields
private Long id;
private Customer customers;
private Integer version;
private String orderNumber;
private Set lineitemses = new HashSet(0);
// Constructors
/** default constructor */
public SampleOrder() {
}
/** minimal constructor */
public SampleOrder(Integer version, String orderNumber) {
this.version = version;
this.orderNumber = orderNumber;
}
/** full constructor */
public SampleOrder(Customer customers, Integer version, String orderNumber,
Set lineitemses) {
this.customers = customers;
this.version = version;
this.orderNumber = orderNumber;
this.lineitemses = lineitemses;
}
// Property accessors
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Customer getCustomers() {
return this.customers;
}
public void setCustomers(Customer customers) {
this.customers = customers;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getOrderNumber() {
return this.orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public Set getLineitemses() {
return this.lineitemses;
}
public void setLineitemses(Set lineitemses) {
this.lineitemses = lineitemses;
}
}
Fetch=”join”
Java DAO:
public List findAll() {
log.debug("finding all Customers instances");
try {
String queryString = "from Customer cus";
Query queryObject = getSession().createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
Java Client:
CustomersDAO dao = new CustomersDAO() ;
List list = dao.findAll() ;
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Customer customer = (Customer) iterator.next();
customer.getOrders().size() ;
}
SQL Output:
Hibernate:
select
customer0_.ID as ID0_,
customer0_.VERSION as VERSION0_,
customer0_.NAME as NAME0_,
customer0_.PASSWORD as PASSWORD0_,
customer0_.EMAIL as EMAIL0_
from
sampledb.dbo.CUSTOMERS customer0_
Hibernate 1:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
Hibernate 2:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
Hibernate 3:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
If we use fetch=’join strategy to retrieve all the customers with their order objects, you will see the different from fetch=”select”.
Java DAO:
public List findAllWithOrders() {
log.debug("finding all Customers instances with Orders");
try {
String queryString = "from Customer cus left join cus.orders";
Query queryObject = getSession().createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
Java Client:
CustomersDAO dao = new CustomersDAO() ;
List list = dao.findAllWithOrders() ;
SQL Output:
Hibernate:
select
customer0_.ID as ID0_0_,
orders1_.ID as ID5_1_,
customer0_.VERSION as VERSION0_0_,
customer0_.NAME as NAME0_0_,
customer0_.PASSWORD as PASSWORD0_0_,
customer0_.EMAIL as EMAIL0_0_,
orders1_.CUSTOMER_ID as CUSTOMER2_5_1_,
orders1_.VERSION as VERSION5_1_,
orders1_.ORDER_NUMBER as ORDER4_5_1_
from
sampledb.dbo.CUSTOMERS customer0_
left outer join
sampledb.dbo.SAMPLEORDERS orders1_
on customer0_.ID=orders1_.CUSTOMER_ID
Summary of Join and Non-join:
1. The attribute “fetch” mapping will be ignored when we use HQL.
2. If we adopt “select” or other non-join fetch strategies, the associated objects will be retrieved in separately. (For our example, it will be separated to 3 independent query SQLs.)
If we adopt “join” fetch strategy, the associated objects will be retrieved with left join query. (For our example, all the associated order objects will be retrieved in a same query SQL with Left Join.)
Fetch=”select”
Java DAO:
public List findAll()
{
log.debug("finding all Customers instances");
try {
String queryString = "from Customer cus where cus.id in (1,2,3)";
Query queryObject = getSession().createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
Java Client:
List list = dao.findAll() ;
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Customer customer = (Customer) iterator.next();
customer.getOrders().size() ;
}
SQL Output:
Hibernate:
select
customer0_.ID as ID0_,
customer0_.VERSION as VERSION0_,
customer0_.NAME as NAME0_,
customer0_.PASSWORD as PASSWORD0_,
customer0_.EMAIL as EMAIL0_
from
sampledb.dbo.CUSTOMERS customer0_
where
customer0_.ID in (
1 , 2 , 3
)
Hibernate 1:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
Hibernate 2:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
Hibernate 3:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID=?
Fetch=”subselect”
Java DAO:
public List findAll()
{
log.debug("finding all Customers instances");
try {
String queryString = "from Customer cus where cus.id in (1,2,3)";
Query queryObject = getSession().createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
Java Client:
List list = dao.findAll() ;
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Customer customer = (Customer) iterator.next();
customer.getOrders().size() ;
}
SQL Output:
Hibernate:
select
customer0_.ID as ID0_,
customer0_.VERSION as VERSION0_,
customer0_.NAME as NAME0_,
customer0_.PASSWORD as PASSWORD0_,
customer0_.EMAIL as EMAIL0_
from
sampledb.dbo.CUSTOMERS customer0_
where
customer0_.ID in (
1 , 2 , 3
)
Hibernate 1:
select
orders0_.CUSTOMER_ID as CUSTOMER2_1_,
orders0_.ID as ID1_,
orders0_.ID as ID5_0_,
orders0_.CUSTOMER_ID as CUSTOMER2_5_0_,
orders0_.VERSION as VERSION5_0_,
orders0_.ORDER_NUMBER as ORDER4_5_0_
from
sampledb.dbo.SAMPLEORDERS orders0_
where
orders0_.CUSTOMER_ID in (
select
customer0_.ID
from
sampledb.dbo.CUSTOMERS customer0_
where
customer0_.ID in (
1 , 2 , 3
)
)
Summary of Select and Subselect:
1. If we use “Select” fetch strategy, each of associated objects query operation will be performed in separately.
2. If we use “Subselect” fetch strategy, all the associated objects query operation will be executed in single query statement. (For our example, Hibernate uses embed-query to optimize the query operation)
To be continue,
Xianyi.Ye