`

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
分享到:
评论

相关推荐

    Hibernate程序高手秘笈.part10-11.rar

    Part11:实战应用与优化 1. **性能调优**:分析影响Hibernate性能的因素,如批处理、缓存策略、连接池等,并给出优化建议。 2. **事务管理**:介绍Hibernate事务处理机制,包括编程式事务管理和声明式事务管理,...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     16.3 一对多和多对多关联的检索策略  16.3.1 立即检索(lazy属性为“false”)  16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     16.3 一对多和多对多关联的检索策略  16.3.1 立即检索(lazy属性为“false”)  16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     16.3 一对多和多对多关联的检索策略  16.3.1 立即检索(lazy属性为“false”)  16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     16.3 一对多和多对多关联的检索策略  16.3.1 立即检索(lazy属性为“false”)  16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即...

    精通hibernate(part 1)共分4个part (孙卫琴)

    - **多对多关联**:介绍如何在Hibernate中实现多对多关联,并给出具体的配置示例。 - **继承映射**:探讨如何使用单表、多表和联合表继承模式来映射具有层次结构的实体。 6. **事务管理** - **本地事务**:讨论...

    jbpm-starters-kit-3.1.2.part1_part2

    jbpm-starters-kit-3.1.2.part1_part2 是一个分卷压缩包,它包含了jbpm-starters-kit的3.1.2版本。jbpm(Business Process Management)是开源的工作流管理系统,用于实现业务流程自动化。这个压缩包很可能包含源...

    文件上传与下载源码 含数据库

    - **文件命名策略**:为了避免文件名冲突,需要设计合理的文件命名策略,例如使用时间戳或UUID。 - **文件大小限制**:为了防止DoS攻击,需要设定上传文件的大小限制。 - **安全性**:确保上传的文件类型安全,...

    JavaWeb轻量级开发全体验邓子云part2

    在这个部分(part2),我们将探讨更多与类库、代码管理、文件上传下载以及电子邮件发送等相关的内容。 首先,类库在JavaWeb开发中扮演着至关重要的角色。它们提供预封装的功能,使开发者能够快速实现特定任务,如...

    上传并显示图片

    本项目利用SSH(Spring、Struts2和Hibernate)框架实现上传图片并即时显示的功能,这为我们提供了一个理解Web应用程序开发中文件上传处理的实例。 首先,Spring框架作为核心的依赖注入(DI)和面向切面编程(AOP)...

    投票系统所需jar文件三

    3. **框架和库**:Spring、Hibernate等框架的jar文件,Spring可以用来管理应用的组件和流程,而Hibernate则可简化数据库操作。 4. **数据验证**:如javax.validation-api.jar,用于对用户输入进行验证,确保投票的...

Global site tag (gtag.js) - Google Analytics