one-to-many 和many-to-many的检索策略分析 package com.macower.hibernate.strategy; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; import org.hibernate.Session; public class BatchCustomerTest extends TestCase { /** * * * @throws Exception */ @SuppressWarnings("unchecked") public void testBatchCustomers() throws Exception { Session session = HibernateUtils.getSession(); //根据lazy和batch—size的属性发送SQL发送,下面有分情况讨论 List<Customer> customers = session.createQuery("from Customer as c") .list(); Iterator<Customer> iter = customers.iterator(); Customer c1 = iter.next(); Customer c2 = iter.next(); Customer c3 = iter.next(); Customer c4 = iter.next(); /* * 1:当没有设置batch-size的时候,每次调用getOrders().iterator()的时候都会发出一条SQL语句进行查询 * * 2:当 <set name="orders" cascade="all" inverse="true" lazy="true" * batch-size="2"> 每两条做一次批量读取,减少数据的查询SQL发送的数量 select orders0_.customer * as customer1_, orders0_.ID as ID1_, orders0_.ID as ID1_0_, * orders0_.NAME as NAME1_0_, orders0_.customer as customer1_0_ from * ORDERS orders0_ where orders0_.customer in (?, ?) * 3:当<set name="orders" cascade="all" inverse="true" lazy="false" * batch-size="2">的时候 在list()就已经将全部的SQL语句发出 * Hibernate: select * customer0_.ID as ID0_, customer0_.NAME as NAME0_ from CUSTOMERS * customer0_ * Hibernate: select orders0_.customer as customer1_, * orders0_.ID as ID1_, orders0_.ID as ID1_0_, orders0_.NAME as * NAME1_0_, orders0_.customer as customer1_0_ from ORDERS orders0_ * where orders0_.customer in (?, ?) * Hibernate: select orders0_.customer * as customer1_, orders0_.ID as ID1_, orders0_.ID as ID1_0_, * orders0_.NAME as NAME1_0_, orders0_.customer as customer1_0_ from * ORDERS orders0_ where orders0_.customer in (?, ?) * 4: 当<set name="orders" cascade="all" inverse="true" lazy="false" batch-size="2" fetch="subselect"> * 此时很明显已经忽略了batch-size这个属性,进行的是子查询SQL如下: * Hibernate: select customer0_.ID as ID0_, customer0_.NAME as NAME0_ from CUSTOMERS customer0_ *Hibernate: select orders0_.customer as customer1_, orders0_.ID as ID1_, orders0_.ID as ID1_0_, *orders0_.NAME as NAME1_0_, orders0_.customer as customer1_0_ *from ORDERS orders0_ where orders0_.customer in *(select customer0_.ID from CUSTOMERS customer0_) * *5:当<set name="orders" cascade="all" inverse="true" lazy="false" batch-size="2" fetch="join"> *此时list方法会忽略迫切的左外连接的策略,此时进行依然是lazy设置的相应属性的策略进行查询。 *如果使用的是session的get方法那么就会采用迫切的左外连接的策略。详见方法testJoinWithGet() *Hibernate: select customer0_.ID as ID0_, customer0_.NAME as NAME0_ from CUSTOMERS customer0_ *Hibernate: select orders0_.customer as customer1_, orders0_.ID as ID1_, *orders0_.ID as ID1_0_, orders0_.NAME as NAME1_0_, orders0_.customer *as customer1_0_ from ORDERS orders0_ *where orders0_.customer in (?, ?) *Hibernate: select orders0_.customer as customer1_, orders0_.ID as ID1_, *orders0_.ID as ID1_0_, orders0_.NAME as NAME1_0_, orders0_.customer *as customer1_0_ from ORDERS orders0_ where orders0_.customer in (?, ?) * */ Iterator orderIter1 = c1.getOrders().iterator(); Iterator orderIter2 = c2.getOrders().iterator(); /* * 2:当 <set name="orders" cascade="all" inverse="true" lazy="true" * batch-size="2"> 进行第二次批量加载 select orders0_.customer as customer1_, * orders0_.ID as ID1_, orders0_.ID as ID1_0_, orders0_.NAME as * NAME1_0_, orders0_.customer as customer1_0_ from ORDERS orders0_ * where orders0_.customer in (?, ?) */ Iterator orderIter3 = c3.getOrders().iterator(); Iterator orderIte4 = c4.getOrders().iterator(); } public void testJoinWithGet() throws Exception { Session session = HibernateUtils.getSession(); /** * 此时会发出left outer join的SQL的查询语句,此时运用了 * <set name="orders" cascade="all" inverse="true" lazy="false" batch-size="2" fetch="join"> * 上的fetch=join的策略。 * Hibernate: select customer0_.ID as ID0_1_, customer0_.NAME as NAME0_1_, * orders1_.customer as customer3_, orders1_.ID as ID3_, orders1_.ID as ID1_0_, orders1_.NAME as NAME1_0_, * orders1_.customer as customer1_0_ from CUSTOMERS customer0_ * left outer join ORDERS orders1_ on customer0_.ID=orders1_.customer where customer0_.ID=? */ session.get(Customer.class, 1); } }