持久化對象三種狀态的概述
Hibernate為了更好的來管理持久化類,特将持久化類分成了三種狀态。在Hibernate中持久化的對象可以劃分為三種狀态,分别為瞬時态,持久态和脫管态,一個持久化類的執行個體可能處于三種不同狀态中的某一種,三種狀态的詳細介紹如下。
-
瞬時态(transient)
瞬時态也稱為臨時态或者自由态,瞬時态的執行個體是由new指令建立、開辟記憶體空間的對象, 不 存 在 持 久 化 标 識 O I D ( 相 當 于 主 鍵 值 ) , 尚 未 與 H i b e r n a t e S e s s i o n 關 聯 \color{red}{不存在持久化辨別OID(相當于主鍵值),尚未與Hibernate Session 關聯} 不存在持久化辨別OID(相當于主鍵值),尚未與HibernateSession關聯,在資料庫中也沒有記錄,失去引用後将被JVN回收。瞬時狀态的對象在記憶體中是孤立存在的,與資料庫中的資料無任何關聯,僅是一個資訊攜帶的載體。
-
持久态(persistent)
持久态的對象 存 在 持 久 化 标 識 O I D , 加 入 到 了 S e s s i o n 緩 存 中 , 并 且 相 關 聯 的 S e s s i o n 沒 有 關 閉 , 在 數 據 庫 中 有 對 應 的 記 錄 \color{red}{存在持久化辨別OID,加入到了Session緩存中,并且相關聯的Session沒有關閉,在資料庫中有對應的記錄} 存在持久化辨別OID,加入到了Session緩存中,并且相關聯的Session沒有關閉,在資料庫中有對應的記錄,每條記錄對應唯一的持久化對象,需要注意的是,持久态對象是在事務還未送出前變成持久态的。
-
脫管态(detached)
脫管态也稱離線态或者遊離态,當某個持久化狀态的執行個體與Session的關聯被關閉時就變成了脫管态。 脫 管 态 對 象 存 在 持 久 化 标 識 O I D , 并 且 仍 然 與 數 據 庫 中 的 數 據 存 在 關 聯 , 隻 是 失 去 了 與 當 前 S e s s i o n 的 關 聯 \color{red}{脫管态對象存在持久化辨別OID,并且仍然與資料庫中的資料存在關聯,隻是失去了與目前Session的關聯} 脫管态對象存在持久化辨別OID,并且仍然與資料庫中的資料存在關聯,隻是失去了與目前Session的關聯,脫管狀态對象發生改變時Hibernate不能檢測到。
區分對象的三種狀态:
配置orm中繼資料:
<?xml version="1.0" encoding="UTF-8"?>
<!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.itheima.domain" >
<class name="Customer" table="cst_customer" >
<id name="cust_id" >
<generator class="increment"></generator>
</id>
<property name="cust_name" column="cust_name" ></property>
<property name="cust_source" column="cust_source" ></property>
<property name="cust_industry" column="cust_industry" ></property>
<property name="cust_level" column="cust_level" ></property>
<property name="cust_linkman" column="cust_linkman" ></property>
<property name="cust_phone" column="cust_phone" ></property>
<property name="cust_mobile" column="cust_mobile" ></property>
</class>
</hibernate-mapping>
封裝Utils工具類:
package pers.zhang.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory sf;
static{
//1 建立,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據配置資訊,建立 SessionFactory對象
sf = conf.buildSessionFactory();
}
//獲得session => 獲得全新session
public static Session openSession(){
//3 獲得session
Session session = sf.openSession();
return session;
}
//獲得session => 獲得與線程綁定的session
public static Session getCurrentSession(){
//3 獲得session
Session session = sf.getCurrentSession();
return session;
}
}
測試方法:
package pers.zhang.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import pers.zhang.domain.Customer;
import pers.zhang.utils.HibernateUtils;
//測試對象的三種狀态
public class Demo {
@Test
public void fun1(){
//1 獲得session
Session session = HibernateUtils.openSession();
//2 控制事務
Transaction tx = session.beginTransaction();
//3執行操作
Customer c = new Customer(); //瞬時狀态對象:沒有持久化辨別OID,沒有被session管理。
c.setCust_name("聯想"); // 瞬時狀态
session.save(c); // 持久态對象:有持久化辨別OID,被session管理。
//4送出事務.關閉資源
tx.commit();
session.close();//脫管态對象:有持久化辨別OID,沒有被session管理。
}
}
customer對象由new關鍵字建立,此時還未與Session進行關聯,它的狀态稱為瞬時态;在執行了session.save(customer)操作後,book對象納入了Session的管理範圍,這時的customer對象變成了持久态對象,此時Session的事務還沒有被送出;程式執行完了commit() 操作并關閉了Session後,customer對象與Session的關聯被關閉,此時customer對象就變成了脫管态。
持久化對象的三種狀态轉換
持久化對象的狀态演化圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csUjRHJ2d5EDWmJ1RiZnTywEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuAjN3UTOxYTMzATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
從圖中可以看出,當一個對象被執行new關鍵字建立後,該對象處于瞬時态;
當對瞬時态對象執行Session的save() 或saveOrUpdate()方法後,該對象将被放入Session的一級緩存,對象進入持久态;當對持久态對象執行evict()、close()或clear()操作後,對下個進入脫管态;當直接執行Session的get()、load()、find()或iterate()等方法從資料庫裡查詢對象時,查詢到的對象也處于持久态;
當對資料庫中的記錄進行update()、saveOrUpdate()以及lock()等操作後,此時脫管态的對象就會過渡到持久态;
由于瞬時态和脫管态的對象不在session的管理範圍,是以會在一段時間後被JVM回收。
持久化對象的三種狀态可以通過調用Session中的一系列方法實作狀态間的轉換,具體如下:
1. 瞬時态轉換到其它狀态
瞬時态的對象由new關鍵字建立,瞬時态對象轉換到其它狀态總結如下:
-
瞬時态轉換為持久态:
執行Session的save()或saveOrUpdate()方法。
-
瞬時态轉換為脫管态:
為瞬時态對象設定持久化辨別OID。
由于持久化對象狀态演化圖中沒有涉及到瞬時态轉換到脫管态的情況,這裡做下簡要說明:脫管态對象存在OID,但是沒有Session的關聯,也就是說脫管态和瞬時态的差別就是OID有沒有值,是以可以同故宮為瞬時态對象設定OID,使其變成脫管态對象。
Customer customer = new Customer();//瞬時态
customer.setCust_id(1);//脫管态
2.持久态對象轉換到其它狀态
持久化對象可以直接通過Hibernate中Session的get()、load()方法,或者Query查詢從資料庫中獲得,持久态對象轉換到其他狀态總結如下:
-
持久态轉換為瞬時态:
執行Session的delete()方法,需要注意的是被删除的持久化對象,不建議再次使用。
-
持久态轉換為脫管态:
執行Session的evict()、close()或clear()方法。evict()方法用于清除一級緩存中某一個對象;close()方法用于關閉Session,清除一級緩存;clear()方法用于清除一級緩存的所有對象。
3.脫管态對象轉換到其他狀态
脫管态對象無法直接獲得,是由其他狀态對象轉換而來的,脫管态對象轉換到其他狀态總結如下:
-
脫管态轉換為持久态:
執行Session的update()、saveOrUpdate()或lock()方法。
-
脫管态轉換為瞬時态:
将脫管态對象的持久化辨別OID設定為null。
由于持久化對象狀态演化圖中沒有涉及到脫管态轉換到瞬時态的情況,這裡做下簡要說明:跟瞬時态轉換到脫管态的情況相似,脫管态和瞬時态的差別就是OID有沒有值,是以可以通過将脫管态對象的OID設定為null,使其程式設計瞬時态對象。
例如:在session.close()操作後,加入代碼
customer.setCust_id(null);
customer對象将由脫管态轉為瞬時态。
持久态對象能夠自動更新資料庫
持久态對象其實有一個非常重要的特性:持久化對象可以自動更新資料庫。
@test
//測試持久化類的持久态對象有自動更新資料庫的能力
public void demo2(){
Session session = HibenateUtils.openSession();
Transaction tx = session.geginTransaction();
//獲得持久态的對象
Customer customer = session.get(Customer.class, 1L);//持久态對象
customer.setCust_name("小明");
//session.update(customer);不用手動調用update方法就可以更新
tx.commit();
session.close();
}
執行測試我們會發線,我們并沒有手動調用update方法,Hibernate就可以将資料自動更新了。持久态對象就有這樣一個功能。持久态對象之是以有這樣的功能其實都依賴了Hibernate的一級緩存。