hibernate的延迟加载
延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询,避免了无谓的性能开销。
延迟加载分类:
01.类级别的查询策略
02.一对多和多对多关联的查询策略
03.多对一关联的查询策略
类级别的查询策略
1.类级别可选的检索策略包括立即检索和延迟检索,默认为延迟检索
1.1立即检索:立即加载检索方法指定的对象,立即发送SQL
1.2 延迟检索:延迟加载检索方法制定的对象.在使用具体的属性时,再进行加载,才发送SQL
2.无论<class>元素的lazy属性是true还是false,Session的get()方法及Query的list()方法在类级别总是使用立即检索策略
3.若<class>元素的lazy属性为true或默认值,Session的load()方法不会执行查询数据库表的SELECT语句,仅返回代理类对象的实例,该代理类实例有如下特征:
 3.1 由Hibernate在运行时采用CGLIB工具动态生成
 3.2 Hibernate创建代理类实例时,仅初始化其OID属性
 3.3在应用程序第一次访问代理类实例的非OID属性时,Hibernate会初始化代理类实例
3.4注意:类级别检索策略仅适用于load()方法

1.创建持久化类
public class Student {
    private int id;
    private String  name;
    private int age;
    private String address;
    private String phone;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}
2.创建Student.hbm.xml配置文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 映射文件开始 -->
<hibernate-mapping package="cn.day05lazy.entity">
    <!--表名称-->
    <class name="Student" table="STUDENT" schema="root" lazy="true">
        <!--列名-->
       <id name="id" column="ID">
           <!--主键生成的策略  native:自动生成主键字段-->
           <generator class="native"></generator>
       </id>
        <property name="name" column="NAME"></property>
        <property name="age" column="AGE"></property>
        <property name="address" column="ADDRESS"></property>
        <property name="phone" column="PHONE"></property>
    </class>
</hibernate-mapping>
3.创建hibernate.cfg.xml大配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 指定数据库所用到的驱动 -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <!-- 指定数据库链接的url,hibernate链接的数据库名 -->
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的用户口令 -->
        <property name="connection.password">root</property>
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <!--格式化sql -->
        <property name="format_sql ">true</property>
        <!-- 打印sql 控制台-->
        <property name="show_sql">true</property>
        <!-- 指定数据库方言 -->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!-- 根据需要自动创建数据库表 -->
        <property name="hbm2ddl.auto">update</property>
        <!--延迟加载-->
        <mapping resource="cn/day05lazy/entity/Student.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>
Lazy设置为true
Load()方法测试结果:
@Test
public void test(){
    Session session = HibernateUtil.getSession();
    Student load = session.load(Student.class, 1);
}
 
Get()方法测试结果:
//类级别延迟加载
@Test
public void test(){
    Session session = HibernateUtil.getSession();
    Student load = session.get(Student.class, 1);
}
 
如果将lazy设置为false,则load()方法的延迟加载取消
//类级别延迟加载
@Test
public void test(){
    Session session = HibernateUtil.getSession();
    Student load = session.load(Student.class, 1);
}
 
一对多和多对多关联的查询策略
在映射文件中,用<set>元素来配置一对多关联及多对多关联关系。<set>元素有lazy和fetch属性
-lazy:主要决定Emps集合被初始化的时机。即到底是在加载Dept对象时就被初始化,还是在程序访问Emps集合时被初始化

01.一对多或者多对多检索策略由lazy和fetch共同确定
Lazy:决定关联对象初始化时机
Fetch:决定SQL语句构建形式
02.fetch取值
Join:迫切左外连接
Select:多条简单SQL(默认值)
Subselect:子查询
03.fetch和lazy组合
解析:fetch=”join” lazy会被忽略,迫切左外连接的立即检索
Fetch=”select” lazy=”false” 多条简单SQL立即检索
Fetch=”select” lazy=”true” 多条语句延迟检索
Fetch=”select” lazy=”extra” 多条语句及其懒惰检索
Fetch=”subselect” lazy=”false” 子查询立即检索
Fetch=”subselect” lazy=”true” 子查询延迟检索
Fetch=”subselect” lazy=”extra” 子查询及其懒惰检索
Extra:极其懒惰,只有访问集合对象的属性时才会加载,访问集合本身的属性时(例如,集合大小,生成count),不会立即加载。
注意:query的list()会忽略映射文件配置的左外连接查询,此时lazy属性重新生效。
一对多延迟加载测试
Lazy设置为true时
核心代码:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.onetomany.entity">
    <!--表名称-->
    <class name="Dept" table="DEPT" schema="root">
        <!--列名-->
       <id name="deptid" column="DEPTID">
           <!--主键生成的策略  native:自动生成主键字段-->
           <generator class="native"></generator>
       </id>
     <property name="deptname" column="DEPTNAME"></property>
        <!--植入set 标签  save-update 保存数据   inverse 消除多余的update语句-->
        <set name="emps" cascade="save-update"  inverse="true" order-by="empno desc" lazy="true">
            <!--多的一方表的外键列-->
            <key column="deptno"></key>
            <one-to-many class="Emp"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
//一对多
@Test
public void test01(){
    Session session = cn.day04mapping.onetomany.util.HibernateUtil.getSession();
    Dept dept = session.get(Dept.class, 24);
    //Set<Emp> emps = dept.getEmps();
}

Lazy设置为false
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.onetomany.entity">
    <!--表名称-->
    <class name="Dept" table="DEPT" schema="root">
        <!--列名-->
       <id name="deptid" column="DEPTID">
           <!--主键生成的策略  native:自动生成主键字段-->
           <generator class="native"></generator>
       </id>
     <property name="deptname" column="DEPTNAME"></property>
        <!--植入set 标签  save-update 保存数据   inverse 消除多余的update语句-->
        <set name="emps" cascade="save-update"  inverse="true" order-by="empno desc" lazy="false">
            <!--多的一方表的外键列-->
            <key column="deptno"></key>
            <one-to-many class="Emp"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
//一对多
@Test
public void test01(){
    Session session = cn.day04mapping.onetomany.util.HibernateUtil.getSession();
    Dept dept = session.get(Dept.class, 24);
    //Set<Emp> emps = dept.getEmps();
}
 
Lazy设置为extra
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.onetomany.entity">
    <!--表名称-->
    <class name="Dept" table="DEPT" schema="root">
        <!--列名-->
       <id name="deptid" column="DEPTID">
           <!--主键生成的策略  native:自动生成主键字段-->
           <generator class="native"></generator>
       </id>
     <property name="deptname" column="DEPTNAME"></property>
        <!--植入set 标签  save-update 保存数据   inverse 消除多余的update语句-->
        <set name="emps" cascade="save-update"  inverse="true" order-by="empno desc" lazy="extra">
            <!--多的一方表的外键列-->
            <key column="deptno"></key>
            <one-to-many class="Emp"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
 //一对多
@Test
public void test01(){
    Session session = cn.day04mapping.onetomany.util.HibernateUtil.getSession();
    Dept dept = session.get(Dept.class, 24);
    //Set<Emp> emps = dept.getEmps();
}

//一对多
@Test
public void test01(){
    Session session = cn.day04mapping.onetomany.util.HibernateUtil.getSession();
    Dept dept = session.get(Dept.class, 24);
    Set<Emp> emps = dept.getEmps();
    emps.size();
}

多对一关联的查询策略

Lazy设置为false
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.manytoone.entity">
    <!--name:表名称  schema 操作数据库的用户名-->
    <class name="Emp" table="EMP" schema="root">
        <!--列名-->
       <id name="empno" column="EMPNO">
           <!--主键生成的策略  native:自动生成主键字段-->
           <generator class="native"></generator>
       </id>
     <property name="ename" column="ENAME"></property>
        <!--多对一 单向关联
        员工是多的一方
        name:Emp中植入一方的属性名称
        column;数据库中外键列的值
        class:植入一方的属性的类型
        -->
        <many-to-one name="dept" column="deptno" class="Dept" lazy="false"></many-to-one>
    </class>
</hibernate-mapping>
//多对一
@Test
public void test03(){
    Session session = cn.day04mapping.manytoone.util.HibernateUtil.getSession();
    cn.day04mapping.manytoone.entity.Emp emp = session.get(cn.day04mapping.manytoone.entity.Emp.class, 1);
}
 
Lazy设置为proxy
<?xml version="1.0"?>
        <!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.manytoone.entity">
<!--name:表名称  schema 操作数据库的用户名-->
<class name="Emp" table="EMP" schema="root">
    <!--列名-->
    <id name="empno" column="EMPNO">
        <!--主键生成的策略  native:自动生成主键字段-->
        <generator class="native"></generator>
    </id>
    <property name="ename" column="ENAME"></property>
    <!--多对一 单向关联
    员工是多的一方
    name:Emp中植入一方的属性名称
    column;数据库中外键列的值
    class:植入一方的属性的类型
    -->
    <many-to-one name="dept" column="deptno" class="Dept" lazy="proxy"></many-to-one>
</class>
</hibernate-mapping>
//多对一
@Test
public void test03(){
    Session session = cn.day04mapping.manytoone.util.HibernateUtil.getSession();
    cn.day04mapping.manytoone.entity.Emp emp = session.get(cn.day04mapping.manytoone.entity.Emp.class, 1);
}
 
Lazy设置为no-proxy
<?xml version="1.0"?>
        <!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <!-- 映射文件开始 -->
<hibernate-mapping package="cn.day04mapping.manytoone.entity">
<!--name:表名称  schema 操作数据库的用户名-->
<class name="Emp" table="EMP" schema="root">
    <!--列名-->
    <id name="empno" column="EMPNO">
        <!--主键生成的策略  native:自动生成主键字段-->
        <generator class="native"></generator>
    </id>
    <property name="ename" column="ENAME"></property>
    <!--多对一 单向关联
    员工是多的一方
    name:Emp中植入一方的属性名称
    column;数据库中外键列的值
    class:植入一方的属性的类型
    -->
    <many-to-one name="dept" column="deptno" class="Dept" lazy="no-proxy"></many-to-one>
</class>
</hibernate-mapping>
//多对一
@Test
public void test03(){
    Session session = cn.day04mapping.manytoone.util.HibernateUtil.getSession();
    cn.day04mapping.manytoone.entity.Emp emp = session.get(cn.day04mapping.manytoone.entity.Emp.class, 1);
   // emp.getDept();
}
 
有关延迟加载就讲到这里。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号