最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Hibernate對象狀態(tài)之間的神奇轉(zhuǎn)換

 更新時間:2019年09月09日 14:18:17   作者:#Temptation  
這篇文章主要介紹了淺談Hibernate對象狀態(tài)之間的神奇轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

狀態(tài)分類

在Hibernate框架中,為了管理持久化類,Hibernate將其分為了三個狀態(tài):

  • 瞬時態(tài)(Transient Object)
  • 持久態(tài)(Persistent Object)
  • 脫管態(tài)(Detached Object)

有很多人好像對這些概念和它們之間的轉(zhuǎn)換不太明白,那么本篇文章就是來解決這些問題的,看完了還不會你來找我。(開個玩笑~~)

詳細(xì)描述

我們先來詳細(xì)地了解一下三種狀態(tài):

1、瞬時態(tài)

對象由new操作符創(chuàng)建,且尚未與Hibernate中的Session關(guān)聯(lián)的對象被認(rèn)為處于瞬時態(tài)。瞬時態(tài)對象不會被持久化到數(shù)據(jù)庫中,也不會賦予持久化標(biāo)識,如果程序中失去了瞬時態(tài)對象的引用,瞬時態(tài)對象將被垃圾回收機(jī)制銷毀。

2、持久態(tài)

持久化實(shí)例在數(shù)據(jù)庫中有對應(yīng)的記錄,并擁有一個持久化標(biāo)識。持久化的實(shí)例可以是剛剛保存的,也可以是剛剛被加載的。無論哪一種,持久化對象都必須與指定的Session對象關(guān)聯(lián)。

3、脫管態(tài)

某個實(shí)例曾經(jīng)處于持久化狀態(tài),但隨著與之關(guān)聯(lián)的Session被關(guān)閉,該對象就變成脫管狀態(tài)。脫管狀態(tài)的引用引用依然有效,對象可繼續(xù)被修改。如果重新讓脫管對象與某個Session關(guān)聯(lián),該脫管對象會重新轉(zhuǎn)換為持久化狀態(tài)。

瞬時態(tài) 持久態(tài) 脫管態(tài)
是否存于Session緩存中 × ×
數(shù)據(jù)庫中是否有對應(yīng)記錄 ×

例如:

public class HibernateTest {

	private Session session;
	private Transaction transaction;

	@Before
	public void before() {
		session = HibernateUtil.getSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void after() {
		transaction.commit();
		session.close();
	}

	@Test
	public void test() {
		Person p = new Person();
		p.setPname("張三");
		p.setAge(20);
		session.save(p);
	}
}

那么在這樣的一個例子中,從創(chuàng)建Person對象到給name和age屬性賦值,這些過程都處于瞬時態(tài),而當(dāng)調(diào)用了session對象的save()方法之后,該對象才從瞬時態(tài)轉(zhuǎn)為了持久態(tài)。而當(dāng)session關(guān)閉之后,該對象又從持久態(tài)轉(zhuǎn)為了脫管態(tài)。

對象狀態(tài)之間的轉(zhuǎn)換

了解了三種對象狀態(tài)的相關(guān)概念后,我們來看一看三種對象狀態(tài)之間是如何神奇地相互轉(zhuǎn)換的。

瞬時態(tài) <——> 持久態(tài)

我們知道當(dāng)創(chuàng)建一個對象之后,該對象即為瞬時態(tài),那么它將如何轉(zhuǎn)換為持久態(tài)呢?
看一個例子:

@Test
public void test() {
	Person p = new Person();
	p.setPid(2);
	p.setPname("李四");
	p.setAge(30);
	session.save(p);
	//session.saveOrUpdate(p);
}

給name和age屬性賦值時,該對象仍然處于瞬時態(tài),這個前面已經(jīng)說過了。但需要注意的是,當(dāng)給主鍵也就是Pid屬性賦值時,該對象將不再處于瞬時態(tài),而是轉(zhuǎn)換為脫管態(tài),因?yàn)榇藭r已經(jīng)有了持久化標(biāo)識,但是并沒有與Session發(fā)生關(guān)聯(lián)。而當(dāng)調(diào)用session對象的update()或者saveOrUpdate()方法時,該對象才會轉(zhuǎn)換為持久態(tài)。
當(dāng)然,調(diào)用session對象的get()、load()、query、find()等方法從數(shù)據(jù)庫中查詢得到的對象也處于持久態(tài)。
而僅僅當(dāng)session對象調(diào)用delete()方法將一個持久化的對象從數(shù)據(jù)庫中刪除后,該對象才從持久態(tài)轉(zhuǎn)為了瞬時態(tài)。

持久態(tài) <——> 脫管態(tài)

當(dāng)調(diào)用session對象的close()、clear()等方法后,該session所關(guān)聯(lián)的對象將從持久態(tài)轉(zhuǎn)為脫管態(tài),此時這些對象失去了相關(guān)session的關(guān)聯(lián)。而要想從脫管態(tài)轉(zhuǎn)回持久態(tài),只需調(diào)用save()、saveOrUpdate()等方法即可。

瞬時態(tài) ——> 脫管態(tài)

這個前面也已經(jīng)說過了,當(dāng)創(chuàng)建對象后調(diào)用setXXX()方法設(shè)置主鍵屬性時,該對象就從瞬時態(tài)轉(zhuǎn)為脫管態(tài),前提是這個主鍵是數(shù)據(jù)庫中存在的。

對象生命周期

在這里插入圖片描述

下面以一個對象從創(chuàng)建到保存至數(shù)據(jù)庫的流程做一個分析:

try {
	Session session = HibernateUtil.openSession();
	//開始事務(wù)
	session.beginTransaction();
	//person對象進(jìn)入瞬時狀態(tài)態(tài)
	Person p = new Person();
	p.setPname("王五");
	p.setAge(40);
	//person對象進(jìn)入持久化狀態(tài)
	session.save(p);
	//提交事務(wù),隱式包含了session.flush()的動作
	session.getTransaction().commit();
	//提交完成后,person處于游離狀態(tài)
} catch (HibernateException e) {
	e.printStackTrace();
	if (session != null)
	session.getTransaction().rollback();
} finally {
	if (session != null)
	session.close();
}

當(dāng)一個對象被實(shí)例化后,該對象是瞬時狀態(tài),當(dāng)調(diào)用session.save(Object)后,該對象被加入到session緩存中,進(jìn)入持久化狀態(tài),這時數(shù)據(jù)庫中還不存在對應(yīng)的記錄。當(dāng)session提交事務(wù)后,數(shù)據(jù)庫生成了對應(yīng)的記錄,但是這里需要注意一點(diǎn),因?yàn)槭聞?wù)提交的時候默認(rèn)會去調(diào)用session.flush()方法來清空緩存,相當(dāng)于調(diào)用了clear()方法,而我們知道,調(diào)用了clear()方法,對象會從持久態(tài)轉(zhuǎn)為脫管態(tài)。而處于脫管態(tài)的對象會被垃圾回收機(jī)制銷毀。這就是一個對象從創(chuàng)建到保存至數(shù)據(jù)庫的完整生命周期過程。

其它

對于對象狀態(tài)有了一定的了解之后,可以用來解釋很多現(xiàn)象。

在Hibernate中,唯有當(dāng)對象從其它狀態(tài)轉(zhuǎn)為持久態(tài)時,它才會去自動生成sql語句,其它時候是不會去重復(fù)生成sql,這就是Hibernate框架提高效率的關(guān)鍵所在。

例如:

@Test
public void test2() {
	Session session = HibernateUtil.getSession();
	Transaction transaction = session.beginTransaction();
	Person p = new Person();
	p.setPname("李四");
	p.setAge(30);
	session.save(p);
	p.setPname("王五");
	session.update(p);
	transaction.commit();
	session.close();
}

我在transaction.commit();這條語句上打了一個斷電,然后調(diào)試運(yùn)行。

在這里插入圖片描述

可以看到,控制臺只輸出了一條sql語句,也就是執(zhí)行save()方法時生成的插入語句,但是執(zhí)行update()方法卻并沒有生成sql。這是因?yàn)樵趫?zhí)行update()方法時,Hibernate框架會去判斷當(dāng)前對象的狀態(tài),它發(fā)現(xiàn)當(dāng)前對象處于持久態(tài),所以不重復(fù)生成sql,只是將持久態(tài)對象的值改變而已,然后調(diào)用commit()方法進(jìn)行事務(wù)提交的時候才去生成更新語句。

我們繼續(xù)看一個例子:

@Test
public void test2() {
	Session session = HibernateUtil.getSession();
	Transaction transaction = session.beginTransaction();
	Person p = new Person();
	p.setPname("張三");
	p.setAge(30);
	session.save(p);//此時該對象從瞬時態(tài)轉(zhuǎn)為持久態(tài),生成sql語句
		
	p.setPname("王五");
	session.save(p);//此時該對象為持久態(tài),不生成sql語句
	
	p.setPname("趙六");
	session.update(p);//此時該對象為持久態(tài),不生成sql語句
	
	transaction.commit();
	session.close();
}

你要知道,這跟你調(diào)用哪個方法是無關(guān)的,關(guān)鍵在于對象的狀態(tài),只有轉(zhuǎn)為持久態(tài)時才會生成sql語句。所以上面的程序段依然只會產(chǎn)生兩條sql,一條是save()方法產(chǎn)生的,一條是commit()方法產(chǎn)生的。
控制臺信息如下:

Hibernate: 
  insert 
  into
    PERSON
    (PNAME, AGE) 
  values
    (?, ?)
Hibernate: 
  update
    PERSON 
  set
    PNAME=?,
    AGE=? 
  where
    PID=?

理解Hibernate的三種狀態(tài),將更有利于理解Hibernate的運(yùn)行機(jī)制,這些可以讓你在開發(fā)中對疑點(diǎn)問題的定位產(chǎn)生關(guān)鍵性的幫助。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入理解Java注解類型(@Annotation)

    深入理解Java注解類型(@Annotation)

    這篇文章主要介紹了深入理解Java注解類型(@Annotation),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 基于Restful接口調(diào)用方法總結(jié)(超詳細(xì))

    基于Restful接口調(diào)用方法總結(jié)(超詳細(xì))

    下面小編就為大家?guī)硪黄赗estful接口調(diào)用方法總結(jié)(超詳細(xì))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Springboot?集成spring?cache緩存的解決方案

    Springboot?集成spring?cache緩存的解決方案

    這篇文章主要介紹了Springboot?集成spring?cache緩存,使用緩存最關(guān)鍵的一點(diǎn)就是保證緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性,本文給大家介紹最常用的緩存操作模式,對Springboot?集成spring?cache緩存操作流程感興趣的朋友一起看看吧
    2022-06-06
  • 10個Java解決內(nèi)存溢出OOM的方法詳解

    10個Java解決內(nèi)存溢出OOM的方法詳解

    在Java開發(fā)過程中,有效的內(nèi)存管理是保證應(yīng)用程序穩(wěn)定性和性能的關(guān)鍵,不正確的內(nèi)存使用可能導(dǎo)致內(nèi)存泄露甚至是致命的OutOfMemoryError(OOM),下面我們就來學(xué)習(xí)一下有哪些解決辦法吧
    2024-01-01
  • Java多線程系列之JDK并發(fā)包舉例詳解

    Java多線程系列之JDK并發(fā)包舉例詳解

    Java并發(fā)包提供了許多用于多線程編程的類和接口,這篇文章主要給大家介紹了關(guān)于Java多線程系列之JDK并發(fā)包的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Spring?Data?JPA框架的核心概念與Repository接口詳解

    Spring?Data?JPA框架的核心概念與Repository接口詳解

    Spring?Data?JPA是Spring基于JPA規(guī)范的基礎(chǔ)上封裝的?套?JPA?應(yīng)?框架,可使開發(fā)者?極簡的代碼即可實(shí)現(xiàn)對數(shù)據(jù)庫的訪問和操作,本篇我們來了解Spring?Data?JPA框架的核心概念與Repository接口
    2022-04-04
  • Java實(shí)現(xiàn)inputstream流的復(fù)制代碼實(shí)例

    Java實(shí)現(xiàn)inputstream流的復(fù)制代碼實(shí)例

    這篇文章主要介紹了Java實(shí)現(xiàn)inputstream流的復(fù)制代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 簡單了解SpringCloud運(yùn)行原理

    簡單了解SpringCloud運(yùn)行原理

    這篇文章主要介紹了簡單了解SpringCloud運(yùn)行原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 詳解Spring中的@Scope注解

    詳解Spring中的@Scope注解

    這篇文章主要介紹了詳解Spring中的@Scope注解,@Scope注解是Spring IOC容器中的一個作用域,在Spring IOC容器中,他用來配置Bean實(shí)例的作用域?qū)ο?需要的朋友可以參考下
    2023-07-07
  • SpringBoot內(nèi)存數(shù)據(jù)導(dǎo)出成Excel的實(shí)現(xiàn)方法

    SpringBoot內(nèi)存數(shù)據(jù)導(dǎo)出成Excel的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于SpringBoot內(nèi)存數(shù)據(jù)導(dǎo)出成Excel的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論

沙田区| 大名县| 庆元县| 永吉县| 宁津县| 绥化市| 富民县| 定日县| 中牟县| 洛隆县| 启东市| 平武县| 东明县| 双鸭山市| 衡水市| 靖州| 宝坻区| 无极县| 集贤县| 花垣县| 易门县| 武平县| 鹤岗市| 隆昌县| 泸定县| 锡林郭勒盟| 米泉市| 林州市| 土默特右旗| 临泽县| 甘南县| 鄢陵县| 石泉县| 启东市| 吴川市| 西宁市| 安徽省| 宣城市| 梁平县| 土默特左旗| 新丰县|