• 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 }

     

  • 相关阅读:
    搭建Vmware Workstation 12 + Kylin 4.02(Ubuntu 16.04) + petalinux + Vivado
    dash 和 bash 切换
    centos的镜像下载
    docker部署redis,kafka
    Centos7下使用mail发送邮件配置
    实现内网主机既能访问yum源,又能curl通baidu,外网nginx的配置
    centos7下使用mysql离线安装包安装mysql5.7
    内网主机使用nginx代理访问阿里yum源
    配置阿里云yum源
    centos下查看cpu核数
  • 原文地址:https://www.cnblogs.com/qjjazry/p/6290832.html
Copyright © 2020-2023  润新知