延迟加载:延迟加载(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();
}
有关延迟加载就讲到这里。