Hibernate5笔记6--Hibernate检索优化

Hibernate检索优化:

  检索即查询。为了减轻DB的访问压力,提高检索效率,Hibernate对检索进行了优化。
  所谓检索优化,指的是对查询语句的执行时机进行了细致、严格的把控:并不是代码中一出现查询语句,马上就在后台调用执行select语句。而是在代码中真正需要时才执行select。即将select的执行进行了最大可能的“延迟”
  对对象进行检索的目的是为了将对象加载到内存,让程序使用其数据。所以,对象检索也称为对象加载。根据检索对象的不同,可以将检索优化分为两类:  (1)当前对象检索优化 (2)关联对象检索优化
  对于不使用优化进行对象检索的过程,称为直接加载;否则称为延迟加载,或懒加载。 延迟加载的底层实现,在Hibernate3.3版本之前使用的是CGLIB生成代理实现的,而3.3版本以后是由javassist代理实现的。若实体类使用final修饰,将无法生成CGLIB代理,即对于3.3版本之前的Hibernate将无法实现延迟加载。考虑到对老版本代码的兼容问题,实体类最好不要使用final修饰。  

  (1)当前对象检索优化:

    对于当前对象进行检索加载,Session中提供了两个方法:get()与load()。  默认情况下,get()为直接加载,而load()为延迟加载
    get()方法的直接加载指,当代码中出现get()时,后台马上会调用执行select语句,将对象直接加载到内存。
    load()方法的延迟加载指,当代码中出现load()时,后台并不会马上调用执行select。只有当代码中真正在访问除了主键id属性以外的其它属性时,才会真正执行select语句,即此时才会将对象真正加载到内存。

    load()方法默认情况下采用延迟加载策略,但也是可以改变的,可以改为直接加载。在该类映射文件的<class/>标签中有个属性lazy,其默认值为true,即采用延迟加载策略。将其值修改为false,load()的执行也将采用直接加载。

  (2)关联对象检索优化:

    对于关联对象的检索,也可进行延迟加载的优化。采用何种优化策略,要依据映射文件的配置。映射文件中对于关联对象检索的优化配置属性有两个lazy、fetch。 
    lazy与fetch各具有若干值,它们不同值的组合,表示不同的对象加载策略。  根据这两个属性配置位置的不同,又分为两种:  (1)多端配置优化  (2)单端配置优化 

    (1)多端加载优化(在一方对象的映射文件中配置属性):

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5   
 6 <hibernate-mapping package="com.tongji.beans">
 7     <class name="Country">
 8         <id name="cid">
 9             <generator class="native"/>
10         </id>
11         <property name="cname"/>
12         <!-- 左外连接查询,不存在延迟加载问题,也就不存在多端加载优化问题 ,所以不用lazy-->
13         <!-- <set name="ministers" cascade="all" fetch="join"> -->
14         <!-- 普通查询(两表分别查询),不使用延迟加载,则查找当前对象的时候,不管关联对象是否用到,都会一起加载 -->
15         <!-- <set name="ministers" cascade="all" fetch="select" lazy="false"> -->
16         <!-- 普通查询,使用延迟加载,则查找当前对象的时候,不加载关联对象,直到用到关联对象的时候,才会加载关联对象 -->
17         <!-- <set name="ministers" cascade="all" fetch="select" lazy="true"> -->
18         <!-- 普通查询,特别延迟,则查找当前对象的时候,不加载关联对象,并且用到关联对象的时候,能用聚合查询的时候,就不做详情查询 -->
19         <!-- <set name="ministers" cascade="all" fetch="select" lazy="extra"> -->
20         <!-- 补充:子查询,效果同普通查询,其实Hibernate5不支持该策略,但为了兼容以前的版本,对subselect进行了保留 -->
21         <!-- <set name="ministers" cascade="all" fetch="subselect" lazy="extra"> -->
22         <!-- 默认使用,fetch="select" lazy="true"这种格式 -->
23         <set name="ministers" cascade="save-update">
24             <key column="countryId"/>
25             <one-to-many class="Minister"/>
26         </set>
27     </class>
28 </hibernate-mapping>

    测试代码:

 1 @Test
 2 public void test01() {
 3     //1. 获取Session
 4     Session session = HbnUtils.getSession();
 5     try {
 6         //2. 开启事务
 7         session.beginTransaction();
 8         //3. 操作
 9         Country country = session.get(Country.class, 1);
10         Set<Minister> ministers = country.getMinisters();
11         //集合大小的输出
12         System.out.println("ministers.size() = " + ministers.size());
13         //集合详情的输出
14         System.out.println(ministers);
15         //4. 事务提交
16         session.getTransaction().commit();
17     } catch (Exception e) {
18         e.printStackTrace();
19         //5. 事务回滚
20         session.getTransaction().rollback();
21     }
22 }

    (2)单端加载优化(在多方对象的映射文件配置属性):

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5   
 6 <hibernate-mapping package="com.tongji.beans">
 7     <class name="Minister">
 8         <id name="mid">
 9             <generator class="native"/>
10         </id>
11         <property name="mname"/>
12         <!-- 关联属性名 -->
13         <!-- 左外连接查询,同多端加载优化 -->
14         <!-- <many-to-one name="country" cascade="save-update" 
15             class="Country" column="countryId" fetch="join"/> -->
16         <!-- 普通查询之直接加载,同多端加载优化 -->
17         <!-- <many-to-one name="country" cascade="save-update" 
18             class="Country" column="countryId" fetch="select" lazy="false"/> -->
19         <!-- 普通查询,是否延迟加载,由关联对象的lazy值决定-->
20         <many-to-one name="country" cascade="save-update" 
21             class="Country" column="countryId" fetch="select" lazy="proxy"/>
22         <!-- 补充:no-proxy和proxy基本相同,但是会对字节码进行加强 -->
23         <!-- <many-to-one name="country" cascade="save-update" 
24             class="Country" column="countryId" fetch="select" lazy="no-proxy"/> -->
25     </class>
26 </hibernate-mapping>
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5   
 6 <hibernate-mapping package="com.tongji.beans">
 7     <!-- 单端加载优化,之普通查询,直接加载-->
 8     <!-- <class name="Country" lazy="false"> -->
 9     <!-- 单端加载优化,之普通查询,延迟加载 ,默认-->
10     <class name="Country" lazy="true">
11         <id name="cid">
12             <generator class="native"/>
13         </id>
14         <property name="cname"/>
15         <set name="ministers" cascade="all">
16             <key column="countryId"/>
17             <one-to-many class="Minister"/>
18         </set>
19     </class>
20 </hibernate-mapping>

    测试代码:

 1 @Test
 2 public void test01() {
 3     //1. 获取Session
 4     Session session = HbnUtils.getSession();
 5     try {
 6         //2. 开启事务
 7         session.beginTransaction();
 8         //3. 操作
 9         Minister minister = session.get(Minister.class, 2);
10         Country country = minister.getCountry();
11         
12         System.out.println("country.id = " + country.getCid());
13         System.out.println("country.name = " + country.getCname());
14         //4. 事务提交
15         session.getTransaction().commit();
16     } catch (Exception e) {
17         e.printStackTrace();
18         //5. 事务回滚
19         session.getTransaction().rollback();
20     }
21 }

 

posted @ 2017-01-16 19:28  拉夫德尔  阅读(1075)  评论(0编辑  收藏  举报