`

Hibernate part 11:一对多/多对多检索策略

 
阅读更多

 

 

 

 类级别的检索策略:

Customer c=(Customer)session.load(Customer.class, 1);

 session的方法直接检索Customer对象,对Customer对象到底采用立即检索,还是延迟检索方式,通过class元素的lazy属性设定

 

get():默认立即检索

load():默认延迟检索

public void loadCustomertrueProxy(){
	Session session=sessionFacoty.openSession();
	Transaction tx=session.beginTransaction(); 
	//此时查询到的c对象是一个代理对象
	Customer c=(Customer)session.load(Customer.class, 1);
	System.out.println(c.getClass());  //代理对象
	c.getClass();   //hibernate不会执行select语句
	c.getId();        //hibernate不会执行select语句
	c.getAge();     //该行hibernate会执行select语句
	tx.commit();
	session.close();  
}

 Hiberante提供了一个工具类,可以在load()延迟加载的情况下手动加载

public void loadCustomertrueProxyInit(){
	Session session=sessionFacoty.openSession();
	Transaction tx=session.beginTransaction(); 
	//此时查询到的c对象是一个代理对象
	Customer c=(Customer)session.load(Customer.class, 1);
	System.out.println(c.getClass());  //代理对象
	//判断代理对象是否被初始化 对集合对象也适用
	if(!Hibernate.isInitialized(c)){
		  System.out.println(c.getClass());  //代理对象
		  System.out.println("没有被初始化");
		  //方法一
		  c.getAge();//会查询select语句
		  //初始化代理对象的方法,hibernate执行select查询,方法二
		  Hibernate.initialize(c);
	}
	tx.commit();
	session.close();  
}

 get/load在Hibernate part 4中已经详细的解释过了

通过修改配置文件,load()可以实现立即检索

<class name="rock.lee.bean.Customer" table="customer" catalog="test" lazy="false">

 此时load()检索方式和get()一样,不会生成代理对象,立即查询Customer对象

无 论 <class> 元素的 lazy 属性是 true 还是 false, Session 的 get() 方法及 Query 的 list() 方法在类级别总是使用立即检索策略;若 <class> 元素的 lazy 属性为 true 或取默认值, Session 的 load() 方法不会执行查询数据表的 SELECT 语句

 

关联级别检索策略:

在映射文件中, 用 <set> 元素来配置一对多关联及多对多关联关系,<set> 元素有 lazy 和 fetch 属性

lazy: 主要决定 orders 集合被初始化的时机. 即到底是在加载 Customer 对象时就被初始化, 还是在程序访问 orders 集合时被初始化

fetch: 取值为 “select” 或 “subselect” 时, 决定初始化 orders 的查询语句的形式;  若把 fetch 设置为 “join”, lazy 属性将被忽略
 

建立测试数据:

 

mysql> select * from orders;
+----+---------------+-------+-------------+
| id | address       | money | customer_id |
+----+---------------+-------+-------------+
|  1 | 林允儿...一环         |    11 |           1 |
|  2 | 林允儿...一环         |    11 |           1 |
|  3 | 林允儿...一环         |    11 |           1 |
|  4 | 林允儿...一环         |    11 |           1 |
|  5 | 林允儿...一环         |    11 |           1 |
|  6 | 林允儿...一环         |    11 |           1 |
|  7 | 孙艺珍...一环          |    11 |           2 |
|  8 | 孙艺珍...一环          |    11 |           2 |
|  9 | 孙艺珍...一环          |    11 |           2 |
| 10 | 孙艺珍...一环          |    11 |           2 |
| 11 | 孙艺珍...一环          |    11 |           2 |
| 12 | 孙艺珍...一环          |    11 |           2 |
+----+---------------+-------+-------------+
12 rows in set (0.00 sec)
mysql> select * from customer;
+----+--------+------+
| id | name   | city |
+----+--------+------+
|  1 | 林允儿      | SH   |
|  2 | 孙艺珍       | BJ   |
+----+--------+------+
2 rows in set (0.00 sec)
 
案例一:fetch="join" lazy被忽略

修改配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="rock.lee.bean.Customer" table="customer" catalog="test" >
		<id name="id" column="id" type="int">
			<generator class="native"></generator>
		</id>
		<set name="orders" cascade="save-update,delete,delete-orphan" inverse="true"  fetch="join">
			<!-- customer表order是中所生成的外键列 -->
			<key column="customer_id"></key>
			<one-to-many class="rock.lee.bean.Order" />
		</set>
		<property name="name" column="name" type="java.lang.String"></property>
		<property name="city" column="city" type="java.lang.String"></property>
	</class>
</hibernate-mapping>

 查询ID为1的Custoemr数据

	@Test
	public void test02() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		Customer c1 = (Customer) session.get(Customer.class,1);
		
		transaction.commit();
		session.close();
	}

 由于使用的是关联查询,所以lazy属性被忽略,立刻查询

Hibernate: 
    select
        customer0_.id as id0_1_,
        customer0_.name as name0_1_,
        customer0_.city as city0_1_,
        orders1_.customer_id as customer4_0_3_,
        orders1_.id as id3_,
        orders1_.id as id1_0_,
        orders1_.address as address1_0_,
        orders1_.money as money1_0_,
        orders1_.customer_id as customer4_1_0_ 
    from
        test.customer customer0_ 
    left outer join
        test.orders orders1_ 
            on customer0_.id=orders1_.customer_id 
    where
        customer0_.id=?



 

 案例二:fetch="select"  多条简单SQL

    lazy="false" 立即检索

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="rock.lee.bean.Customer" table="customer" catalog="test" >
		<id name="id" column="id" type="int">
			<generator class="native"></generator>
		</id>
		<set name="orders" cascade="save-update,delete,delete-orphan" inverse="true"  fetch="select" lazy="false">
			<!-- customer表order是中所生成的外键列 -->
			<key column="customer_id"></key>
			<one-to-many class="rock.lee.bean.Order" />
		</set>
		<property name="name" column="name" type="java.lang.String"></property>
		<property name="city" column="city" type="java.lang.String"></property>
	</class>
</hibernate-mapping>
 先查customer,在查orders,使用的都是简单查询语句
Hibernate: 
    select
        customer0_.id as id0_0_,
        customer0_.name as name0_0_,
        customer0_.city as city0_0_ 
    from
        test.customer customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        orders0_.customer_id as customer4_0_1_,
        orders0_.id as id1_,
        orders0_.id as id1_0_,
        orders0_.address as address1_0_,
        orders0_.money as money1_0_,
        orders0_.customer_id as customer4_1_0_ 
    from
        test.orders orders0_ 
    where
        orders0_.customer_id=?

 

lazy="true"  延迟检索

<set name="orders" cascade="save-update,delete,delete-orphan" inverse="true"  fetch="select" lazy="true">

也是两条简单SQL语句,但因为是延迟检索,所以获取order数据是才会查询orders表
   

lazy="extra" 极其懒惰 (比延迟更加延迟) 增强延迟检索

 

<set name="orders" cascade="save-update,delete,delete-orphan" inverse="true"  fetch="select" lazy="extra">
 
	@Test
	public void test02() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		Customer c1 = (Customer) session.get(Customer.class,1);
		System.out.println(c1.getOrders().size());
		System.out.println(c1.getOrders().iterator().next().getAddress());
		
		transaction.commit();
		session.close();
	}
只要不查看order中的数据,就不会发出查询语句
--Hibernate: Customer c1 = (Customer) session.get(Customer.class,1);
    select
        customer0_.id as id0_0_,
        customer0_.name as name0_0_,
        customer0_.city as city0_0_ 
    from
        test.customer customer0_ 
    where
        customer0_.id=?
--Hibernate: System.out.println(c1.getOrders().size());
    select
        count(id) 
    from
        test.orders 
    where
        customer_id =?
--Hibernate: System.out.println(c1.getOrders().iterator().next().getAddress());
    select
        orders0_.customer_id as customer4_0_1_,
        orders0_.id as id1_,
        orders0_.id as id1_0_,
        orders0_.address as address1_0_,
        orders0_.money as money1_0_,
        orders0_.customer_id as customer4_1_0_ 
    from
        test.orders orders0_ 
    where
        orders0_.customer_id=?
 
案例三:fetch="subselect"

    lazy="false" 立即检索
    lazy="true"  延迟检索
    lazy="extra" 极其懒惰 (增强延迟检索)

SQL的查询型式是子查询


 

  • 当设置 <set> lazy="true"  第一次调用 集合 size()、 iterator() 、isEmpty() 、contains() 都会调用Hibernate.initialize() 对延迟集合初始化
  • 当设置 <set> lazy="extra" 调用集合 iterator()导致集合初始化, 调用 size() 、isEmpty() 、contains() 不会对集合初始化
  • 使用get/load 查询customer时,配置fetch="join" 采用迫切左外连接查询,order会被查询, 采用立即检索 lazy被忽略,如果使用Query的list方法查询,根据HQL生成SQL语句,fetch="join" 会被忽略 , lazy 重新生效

 

批量检索:

 

  • 大小: 55.2 KB
  • 大小: 138.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics