• hibernate的延迟加载


    延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询,避免了无谓的性能开销。

    延迟加载分类:

     01.类级别的查询策略

     02.一对多和多对多关联的查询策略

     03.多对一关联的查询策略

    类级别的查询策略

    1.类级别可选的检索策略包括立即检索延迟检索默认为延迟检索

        1.1立即检索:立即加载检索方法指定的对象,立即发送SQL

        1.2 延迟检索:延迟加载检索方法制定的对象.在使用具体的属性时,再进行加载,才发送SQL

     2.无论<class>元素的lazy属性是true还是falseSessionget()方法及Querylist()方法在类级别总是使用立即检索策略

     3.<class>元素的lazy属性为true或默认值,Sessionload()方法不会执行查询数据库表的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>元素有lazyfetch属性

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

    01.一对多或者多对多检索策略由lazyfetch共同确定

        Lazy:决定关联对象初始化时机

        Fetch:决定SQL语句构建形式

    02.fetch取值

        Join:迫切左外连接

        Select:多条简单SQL(默认值)

        Subselect:子查询

    03.fetchlazy组合

    解析: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),不会立即加载。

    注意:querylist()会忽略映射文件配置的左外连接查询,此时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();
    }

     

     有关延迟加载就讲到这里。

  • 相关阅读:
    我从Linux走来,选择了Windows
    静态路由(三路由)
    设置跨交换机VLAN
    服务器只能被动接受
    理解 atime,ctime,mtime (下)
    理解 atime,ctime,mtime (上)
    visualvm连接服务器jvm进行监控
    mysql 日期函数格式
    关于springmvc跨域
    Javassist初体验
  • 原文地址:https://www.cnblogs.com/sujulin/p/8150226.html
Copyright © 2020-2023  润新知