1. 程式人生 > >hibernate的延遲加載

hibernate的延遲加載

pack 默認值 ctype ddr dtd save als map true

延遲加載:延遲加載(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();
}

技術分享圖片

有關延遲加載就講到這裏。

hibernate的延遲加載