延迟加载:延迟加载(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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></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"?>
<!DOCTYPEhibernate-configurationPUBLIC
"-//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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></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 ></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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></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 ></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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></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 ></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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></generator>
</id>
<property name="ename" column="ENAME"></property>
<!--多对一 单向关联
员工是多的一方
name:Emp中植入一方的属性名称
column;数据库中外键列的值
class:植入一方的属性的类型
-->
<many-to-one name="dept" column="deptno" 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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></generator>
</id>
<property name="ename" column="ENAME"></property>
<!--多对一 单向关联
员工是多的一方
name:Emp中植入一方的属性名称
column;数据库中外键列的值
class:植入一方的属性的类型
-->
<many-to-one name="dept" column="deptno" 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"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//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 ></
知识推荐
- 分享webpack打包
- 生成二维码的 jQuery 插件:jquery.qrcode.js的中文乱码问题
- threejs学习笔记01
- Vue2.0中的Ajax请求
- 来腾讯云开发者实验室 学习.NET Core 2.0
- JSP Web第七章整理复习 Servlet基础知识
- php从入门到精通需要多久?
- nodejs+nginx配置gzip压缩
- JQuery 获取表格中的数据
- 两行代码搞定js对象深浅拷贝
- 通过双重for循环来找到JSON中不反复的数据
- JS高级——arguments
- php5.4 升级至php5.6遇到到问题
- 计算机网络(NETWORK 部分二) 第3-4天
- Jquery内容改变时触发事件
- Apache、Nginx与Tomcat的区别
- Jquery浅克隆与深克隆
- Jsoncpp的使用