第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Hibernate 持久化對(duì)象的各種狀態(tài)

1. 前言

本節(jié)課和大家聊聊持久化對(duì)象的 3 種狀態(tài)。通過(guò)本節(jié)課程,你將了解到:

  • 持久化對(duì)象的 3 種狀態(tài);
  • 什么是對(duì)象持久化能力。

2. 持久化對(duì)象的狀態(tài)

程序運(yùn)行期間的數(shù)據(jù)都是存儲(chǔ)在內(nèi)存中。內(nèi)存具有臨時(shí)性。程序結(jié)束、計(jì)算機(jī)掛機(jī)…… 內(nèi)存中的數(shù)據(jù)將不復(fù)存在。

重要的數(shù)據(jù),需要使用持久化技術(shù)將數(shù)據(jù)保存到永久性設(shè)備上。Hibernate 能夠通過(guò) PO(持久化對(duì)象) 將數(shù)據(jù)持久化到數(shù)據(jù)庫(kù)。

Hibernate 對(duì) PO 進(jìn)行操作期間,PO 本身會(huì)發(fā)生一系列的狀態(tài)變化。

2.1 瞬時(shí)狀態(tài)(Transient)

分析一段保存數(shù)據(jù)的實(shí)例:

使用 Hibernate 保存數(shù)據(jù)之前,須先在程序中創(chuàng)建一個(gè)名為 stuPO

Student stu=new Student("PO對(duì)象的瞬時(shí)狀態(tài)", "男");  

PO 在程序運(yùn)行的內(nèi)存中存在,數(shù)據(jù)庫(kù)中沒(méi)有。PO 此時(shí)處于瞬時(shí)狀態(tài) (Transient)。

瞬時(shí)狀態(tài)下的 PO 特征如下:

  • 程序中有、數(shù)據(jù)庫(kù)中沒(méi)有此對(duì)象的相關(guān)信息;
  • 對(duì)象的標(biāo)識(shí)性屬性(對(duì)應(yīng)表中主鍵的那個(gè)屬性) 為空;
  • 如果不使用 Session 對(duì)象的相關(guān)方法進(jìn)行數(shù)據(jù)庫(kù)請(qǐng)求操作,程序退出時(shí)瞬時(shí)狀態(tài)的對(duì)象信息會(huì)丟失。

2.2 持久化狀態(tài)( Persistent )

創(chuàng)建 PO 后,使用 Session 的相關(guān)方法,如 save() 方法向數(shù)據(jù)庫(kù)提交保存請(qǐng)求:

Student stu=new Student("PO對(duì)象的瞬時(shí)狀態(tài)", "男");
session.save(stu);  

此時(shí) PO 在程序中有,數(shù)據(jù)庫(kù)中也有,狀態(tài)便由瞬時(shí)狀態(tài)轉(zhuǎn)變成為持久化狀態(tài)(Persistent)

持久化狀態(tài)下的 PO 有如下幾個(gè)特征:

  • 程序、數(shù)據(jù)庫(kù)中都有 PO 的信息;
  • 對(duì)象的標(biāo)識(shí)屬性的值為數(shù)據(jù)庫(kù)中對(duì)應(yīng)記錄的主鍵值;
  • 持久化狀態(tài)最大的特點(diǎn)是 PO 處于 Session 生命周期之內(nèi)。此狀態(tài)下的 PO 具有持久化能力。

2.3 游離狀態(tài)(Detached)

PO持久化狀態(tài)一直維持到 Session 對(duì)象關(guān)閉。如果 Session 對(duì)象關(guān)閉了,此 PO 的狀態(tài)將由持久化狀態(tài)轉(zhuǎn)變成游離狀態(tài) (Detached)。

游離狀態(tài)時(shí) PO 的特點(diǎn):

  • 程序、數(shù)據(jù)庫(kù)都有 PO 的信息;
  • 但是,此狀態(tài)下的 PO 不具有持久化能力。

PO 不會(huì)一直停留在某一個(gè)狀態(tài)上,PO 隨時(shí)可以在 3 種狀態(tài)之間進(jìn)行切換。

圖片描述

從上圖可看出,PO3 種狀態(tài)之間的相互演變都是通過(guò)調(diào)用 Session 對(duì)象的相關(guān)方法實(shí)現(xiàn)的。

由此看來(lái),Session 對(duì)象被稱為持久化容器是有道理的。

由上圖可知,處于瞬時(shí)狀態(tài)游離狀態(tài)的對(duì)象才有可能被 JVM 垃圾回收器回收。

3. 對(duì)象持久化能力

知道了 PO3 種狀態(tài)。自然會(huì)問(wèn):不同狀態(tài)下的對(duì)象對(duì)實(shí)際操作有什么實(shí)際指導(dǎo)意義?

3 種狀態(tài)中,持久化狀態(tài)的意義最大,如果 PO 處于持久化狀態(tài),此時(shí) PO 就具有持久化能力。

所謂對(duì)象持久化能力,通俗理解:

程序中的數(shù)據(jù)發(fā)生變化,會(huì)自動(dòng)同步到數(shù)據(jù)庫(kù)中。

演示一段數(shù)據(jù)更新實(shí)例,更新之前先查詢數(shù)據(jù):

try {
    transaction = session.beginTransaction();
    //查詢學(xué)生
    Student stu=(Student)session.load(Student.class, new Integer(2));
    //修改學(xué)生信息
    
    //執(zhí)行更新操作
    
    transaction.commit();
} catch (Exception e) {
    transaction.rollback();
} finally {
    session.close();
}  

通過(guò) Sessionget() 方法查詢出來(lái)的 stu 對(duì)象,此時(shí)就處于持久化狀態(tài)。

在” 修改學(xué)生信息 “的注釋下添加一行代碼:

stu.setStuName("持久化狀態(tài)就是這么牛"); 

不需要調(diào)用 Session 中的任何其它方法,執(zhí)行代碼,程序中修改的數(shù)據(jù)立即同步到數(shù)據(jù)庫(kù)中。

這就是持久化狀態(tài)的特點(diǎn):通過(guò) PO 自動(dòng)同步程序與數(shù)據(jù)庫(kù)中的數(shù)據(jù)。

所謂對(duì)象持久化能力本質(zhì)上還是 Session 給的。
Session 記錄對(duì)象是否處于持久化狀態(tài),并充當(dāng)后臺(tái)靠山。處于持久狀態(tài)的對(duì)象與數(shù)據(jù)庫(kù)之間的數(shù)據(jù)同步,只是不需要 Session 顯示調(diào)用。

除了 get()、load()方法。save()、update()、saveOrUpdate()、persis()、megre() 方法都可稱為持久化方法。

調(diào)用這些方法后,能讓對(duì)象進(jìn)入持久化狀態(tài),Session 記錄并且默默維持 PO 中數(shù)據(jù)與數(shù)據(jù)庫(kù)中數(shù)據(jù)的同步。

3.1 save() 和 persist() 方法

saveOrUpdate( ) 方法很好理解,是 save( )update( ) 方法的綜合簡(jiǎn)化版,內(nèi)在本質(zhì)沒(méi)改變。

save()persist() 方法有細(xì)節(jié)上的區(qū)別。
save() 方法原型:

public Serializable save(Object object);

上一段 save ( ) 方法的測(cè)試實(shí)例:

try {
    Student  stu = new Student("save()方法", "男");
    Serializable  stuId = session.save(stu);
    System.out.println("----------輸出學(xué)生編號(hào)Id---------");
    System.out.println(stu.getStuId());
    System.out.println(stuId);
    System.out.println("----------事務(wù)在后面-------"); 
    transaction = session.beginTransaction();
    transaction.commit();
} catch (Exception e) {
    transaction.rollback();  
} finally {
    session.close();
}  

輸出結(jié)果:

Hibernate: 
    insert 
    into
        Student
        (stuName, stuPassword, stuPic, stuSex) 
    values
        (?, ?, ?, ?)
----------輸出學(xué)生編號(hào)Id---------
40
40
----------事務(wù)在后面------- 

結(jié)果即結(jié)論:

Save() 方法可以在事務(wù)之外執(zhí)行;
有一個(gè)關(guān)鍵點(diǎn)需要引起重視:

無(wú)論是在事務(wù)之內(nèi)還是事務(wù)之外,save() 方法都會(huì)向數(shù)據(jù)庫(kù)發(fā)送了一條 Sql 語(yǔ)句請(qǐng)求,控制臺(tái)輸出結(jié)果是一樣的。

但是:

  • 如果程序中 Hibernate 不顯示發(fā)送事務(wù)提交指令,數(shù)據(jù)會(huì)回滾(丟失);
  • 只有當(dāng)數(shù)據(jù)庫(kù)系統(tǒng)接收到程序中發(fā)送過(guò)來(lái)的事務(wù)提交指令后,才會(huì)真正意義上保存。

很好理解,因?yàn)槭聞?wù)是交給 Hibernate 管理的,數(shù)據(jù)庫(kù)接收到插入指令后,在沒(méi)有明確事務(wù)提交指令之前,只會(huì)把數(shù)據(jù)緩存在內(nèi)存中。
也就是說(shuō),雖然 save() 方法看起來(lái)不依賴事務(wù)就可插入數(shù)據(jù),但,沒(méi)有事務(wù)組件的指令,最后也是虛行一場(chǎng)。

persist() 方法原型:

public void persist(Object object);  

上一段 persist() 測(cè)試實(shí)例:

try {
    Student stu = new Student("persist()方法", "男");
    session.persist(stu);
    System.out.println("----------輸出學(xué)生編號(hào)Id---------");
    System.out.println(stu.getStuId());
    System.out.println("----------事務(wù)在后面-------");
    transaction = session.beginTransaction(); 
    System.out.println("-------------事務(wù)提交---------------");
    transaction.commit();
    System.out.println(stu.getStuId());
} catch (Exception e) {
    transaction.rollback();
} finally {
    session.close();
}

輸出結(jié)果:

----------輸出學(xué)生編號(hào)Id---------
null
----------事務(wù)在后面-------
-------------事務(wù)提交---------------
Hibernate: 
  insert 
  into
  Student
  (stuName, stuPassword, stuPic, stuSex) 
  values
  (?, ?, ?, ?)
39 

persist() 方法只有當(dāng)事務(wù)提交后,才會(huì)發(fā)送 Sql 請(qǐng)求,數(shù)據(jù)直接寫(xiě)入數(shù)據(jù)庫(kù),方法本身沒(méi)有返回值。

save() 和 persist() 方法區(qū)別:

  • 在事務(wù)之內(nèi)調(diào)用時(shí),兩者區(qū)別不大;事務(wù)之外,區(qū)別明顯。
  • save() 返回主鍵值,persist() 方法沒(méi)有返回值;
  • persist() 完全依賴事務(wù)組件,否則不會(huì)提交 Sql 請(qǐng)求;
  • persist() 方法除了可進(jìn)行 save 操作,還可以進(jìn)行 update 操作。

3.2 merge() 方法

方法原型:

 public Object  merge(Object object);  

merge() 方法和 persist() 方法類似, 區(qū)別在于:

  • merge() 方法接收一個(gè) PO 作為參數(shù),創(chuàng)建并返回此 PO 的副本對(duì)象;
  • 此副本對(duì)象具有對(duì)象持久化能力。這一點(diǎn)是 merge() 方法與其他方法最大的不同。

上一段實(shí)例:

try{
    transaction = session.beginTransaction();
    //查詢出來(lái)的stu具有持久化能力
    Student stu = (Student) session.get(Student.class, new Integer(2));    
    //轉(zhuǎn)stu對(duì)象持久化狀態(tài)轉(zhuǎn)變成游離狀態(tài)
    session.clear();
    //stu_對(duì)象具有持久化能力
    Student stu_ = (Student) session.merge(stu);
    //這個(gè)操作不能同步到數(shù)據(jù)庫(kù)
    stu.setStuName("我已經(jīng)不具有持久化能力");
    //這個(gè)操作能同步到數(shù)據(jù)庫(kù)
    stu_.setStuName("我具有持久化能力");
    transaction.commit();
} catch(Exception e) {
    transaction.rollback();
} finally {
    session.close();
}  

merge() 方法返回的 stu 對(duì)象的副本 stu_,此對(duì)象具有持久化能力。執(zhí)行下面代碼,數(shù)據(jù)能同步到數(shù)據(jù)庫(kù)中。

stu_.setStuName("我具有持久化能力");  

Session 中提供的每一個(gè)方法都有其實(shí)際意義。

特別是 merge() 方法,既可以保護(hù)原對(duì)象中的數(shù)據(jù)不被污染,又能行使數(shù)據(jù)庫(kù)同步操作。

在很多場(chǎng)景里都會(huì)有這個(gè)需求。

4. 小結(jié)

本節(jié)課程講解 PO 對(duì)象的 3 種狀態(tài),以及 3 種狀態(tài)之間的轉(zhuǎn)化方式。了解處于持久化狀態(tài)的 PO 具有持久化能力,這是 Hibernate 提供的一個(gè)很棒的 程序中對(duì)象數(shù)據(jù)庫(kù)數(shù)據(jù)自動(dòng)同步的方案。

也是一種快速開(kāi)發(fā)方案。

本節(jié)課區(qū)分了幾個(gè)常用方法的差異性。但真相似乎就是:大家都和持久化狀態(tài)有關(guān)系。