真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Hibernate三種狀態(tài)的轉(zhuǎn)換示例

小編給大家分享一下Hibernate三種狀態(tài)的轉(zhuǎn)換示例,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

成都創(chuàng)新互聯(lián)公司提供高防服務(wù)器租用、云服務(wù)器、香港服務(wù)器、內(nèi)江機(jī)房主機(jī)托管

一、遇到的神奇的事情

使用jpa操作數(shù)據(jù)庫,當(dāng)我使用findAll()方法查處一個List的對象后,給對這個list的實(shí)體進(jìn)行了一些操作,并沒有調(diào)用update 或者 saveOrUpdate方法,更改后的數(shù)據(jù)卻神奇的保存到數(shù)據(jù)庫里面去了。

最后簡單粗暴的解決辦法是把這份從數(shù)據(jù)里面查出來的List 復(fù)制了一份,然后再操作,再返回。數(shù)據(jù)就正常了,數(shù)據(jù)庫也沒更新。后面找了資料才發(fā)現(xiàn)是jpa是對hibernate的封裝,底層是hibernate,這是hibernate的持久狀態(tài)搞的鬼。

二、hibernate 的三種狀態(tài)

1. 瞬時狀態(tài) (Transient)

當(dāng)我們通過Java的new關(guān)鍵字來生成一個實(shí)體對象時,這時這個實(shí)體對象就處于自由狀態(tài),如下:

Customer customer=new Customer(“zx”,27,images);

這時customer對象就處于自由狀態(tài),為什么說customer對象處于自由狀態(tài)呢?這是因?yàn)椋藭rcustomer只是通過JVM獲得了一塊內(nèi)存空間,還并沒有通過Session對象的save()方法保存進(jìn)數(shù)據(jù)庫,因此也就還沒有納入Hibernate的緩存管理中,也就是說customer對象現(xiàn)在還自由的游蕩于Hibernate緩存管理之外。所以我們可以看出自由對象最大的特點(diǎn)就是,在數(shù)據(jù)庫中不存在一條與它對應(yīng)的記錄。

瞬時對象特點(diǎn):

  • 不和 Session 實(shí)例關(guān)聯(lián)

  • 在數(shù)據(jù)庫中沒有和瞬時對象關(guān)聯(lián)的記錄

2. 持久狀態(tài) (Persistent)

持久化對象就是已經(jīng)被保存進(jìn)數(shù)據(jù)庫的實(shí)體對象,并且這個實(shí)體對象現(xiàn)在還處于Hibernate的緩存管理之中。這是對該實(shí)體對象的任何修改,都會在清理緩存時同步到數(shù)據(jù)庫中。如下所示:

Customer customer=new Customer(“zx”,27,images);

tx=session.beginTransaction();

session.save(customer);

customer=(Customer)session.load(Customer.class,”1”);

customer.setAge(28);

tx.commit();

這時我們并沒有顯示調(diào)用session.update()方法來保存更新,但是對實(shí)體對象的修改還是會同步更新到數(shù)據(jù)庫中,因?yàn)榇藭rcustomer對象通過save方法保存進(jìn)數(shù)據(jù)庫后,已經(jīng)是持久化對象了,然后通過load方法再次加載它,它仍然是持久化對象,所以它還處于Hibernate緩存的管理之中,這時當(dāng)執(zhí)行tx.commit()方法時,Hibernate會自動清理緩存,并且自動將持久化對象的屬性變化同步到到數(shù)據(jù)庫中。

持久的實(shí)例在數(shù)據(jù)庫中有對應(yīng)的記錄,并擁有一個持久化標(biāo)識 (identifier).

持久對象總是與 Session 和 Transaction 相關(guān)聯(lián),在一個 Session 中,對持久對象的改變不會馬上對數(shù)據(jù)庫進(jìn)行變更,而必須在 Transaction 終止,也就是執(zhí)行 commit() 之后,才在數(shù)據(jù)庫中真正運(yùn)行 SQL 進(jìn)行變更,持久對象的狀態(tài)才會與數(shù)據(jù)庫進(jìn)行同步。在同步之前的持久對象稱為臟 (dirty) 對象。

瞬時對象轉(zhuǎn)為持久對象:

  • 通過 Session 的 save() 和 saveOrUpdate() 方法把一個瞬時對象與數(shù)據(jù)庫相關(guān)聯(lián),這個瞬時對象就成為持久化對象。

  • 使用 fine(),get(),load() 和 iterater() 待方法查詢到的數(shù)據(jù)對象,將成為持久化對象。

持久化對象的特點(diǎn):

  • 和 Session 實(shí)例關(guān)聯(lián)

  • 在數(shù)據(jù)庫中有和持久對象關(guān)聯(lián)的記錄

3. 脫管狀態(tài) (Detached)

當(dāng)一個持久化對象,脫離開Hibernate的緩存管理后,它就處于游離狀態(tài),游離對象和自由對象的最大區(qū)別在于,游離對象在數(shù)據(jù)庫中可能還存在一條與它對應(yīng)的記錄,只是現(xiàn)在這個游離對象脫離了Hibernate的緩存管理,而自由對象不會在數(shù)據(jù)庫中出現(xiàn)與它對應(yīng)的數(shù)據(jù)記錄。如下所示:

Customer customer=new Customer(“zx”,27,images);

tx=session.beginTransaction();

session.save(customer);

customer=(Customer)session.load(Customer.class,”1”);

customer.setAge(28);

tx.commit();

session.close();

當(dāng)session關(guān)閉后,customer對象就不處于Hibernate的緩存管理之中了,但是此時在數(shù)據(jù)庫中還存在一條與customer對象對應(yīng)的數(shù)據(jù)記錄,所以此時customer對象處于游離態(tài);

與持久對象關(guān)聯(lián)的 Session 被關(guān)閉后,對象就變?yōu)槊摴軐ο?。對脫管對象的引用依然有效,對象可繼續(xù)被修改。

脫管對象特點(diǎn):

  • 本質(zhì)上和瞬時對象相同

  • 只是比愛瞬時對象多了一個數(shù)據(jù)庫記錄標(biāo)識值 id.

持久對象轉(zhuǎn)為脫管對象:

當(dāng)執(zhí)行 close() 或 clear(),evict() 之后,持久對象會變?yōu)槊摴軐ο蟆?/p>

瞬時對象轉(zhuǎn)為持久對象:

通過 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脫管對象變?yōu)槌志脤ο蟆?/p>

三、三種狀態(tài)的轉(zhuǎn)換

Hibernate三種狀態(tài)的轉(zhuǎn)換示例

四、舉例子

結(jié)合 save(),update(),saveOrUpdate() 方法說明對象的狀態(tài)

(1) Save() 方法將瞬時對象保存到數(shù)據(jù)庫,對象的臨時狀態(tài)將變?yōu)槌志没癄顟B(tài)。當(dāng)對象在持久化狀態(tài)時,它一直位于 Session 的緩存中,對它的任何操作在事務(wù)提交時都將同步到數(shù)據(jù)庫,因此,對一個已經(jīng)持久的對象調(diào)用 save()或 update() 方法是沒有意義的。如:

Student stu = new Strudnet();

 

stu.setCarId(“200234567”);

 

stu.setId(“100”);

 

// 打開 Session, 開啟事務(wù)

 

session.save(stu);

 

stu.setCardId(“20076548”);

 

session.save(stu); // 無效

 

session.update(stu); // 無效

 

// 提交事務(wù),關(guān)閉 Session

(2) update() 方法兩種用途重新關(guān)聯(lián)脫管對象為持久化狀態(tài)對象,顯示調(diào)用 update() 以更新對象。調(diào)用 update() 只為了關(guān)聯(lián)一個脫管對象到持久狀態(tài),當(dāng)對象已經(jīng)是持久狀態(tài)時,調(diào)用 update() 就沒有多大意義了。如:

// 打開 session ,開啟事務(wù) 

 

stu = (Student)session.get(Student.class,”123456”);

 

stu.setName(“Body”);

 

session.update(stu); // 由于 stu 是持久對象,必然位于 Session 緩沖中,

 

對 stu 所做的變更將 // 被同步到數(shù)據(jù)庫中。所以 update() 是沒有意義的,可以不要這句效果一樣的。

 

// 提交事務(wù),關(guān)閉 Session

 

Hibernate 總是執(zhí)行 update 語句,不管這個脫管對象在離開 Session 之后有沒有更改過,在清理緩存時 Hibernate總是發(fā)送一條 update 語句,以確保脫管對象和數(shù)據(jù)庫記錄的數(shù)據(jù)一致,如:

 

Student stu = new Strudnet();

 

stu.setCarId(“1234”);

 

// 打開 Session1, 開啟事務(wù)

 

session1.save(stu);

 

// 提交事務(wù),關(guān)閉 Session1

 

stu.set(“4567”); // 對脫管對象進(jìn)行更改

 

// 打開 Session2, 開啟事務(wù)

 

session2.update(stu);

 

// 提交事務(wù),關(guān)閉 Session2

注:即使把 session2.update(stu); 這句去掉,提交事務(wù)時仍然會執(zhí)行一條 update() 語句。

如果希望只有脫管對象改變了, Hibernate 才生成 update 語句,可以把映射文件中 標(biāo)簽的 select-before-update 設(shè)為 true, 這種會先發(fā)送一條 select 語句取得數(shù)據(jù)庫中的值,判斷值是否相同,如果相同就不執(zhí)行 update語句。不過這種做法有一定的缺點(diǎn),每次 update 語句之前總是要發(fā)送一條多余的 select 語句,影響性能。對于偶爾更改的類,設(shè)置才是有效的,對于經(jīng)常要更改的類這樣做是影響效率的。

(3) saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,對于傳入的對象, saveOrUpdate() 首先判斷其是脫管對象還是臨時對象,然后調(diào)用合適的方法。

看完了這篇文章,相信你對“Hibernate三種狀態(tài)的轉(zhuǎn)換示例”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


本文名稱:Hibernate三種狀態(tài)的轉(zhuǎn)換示例
文章網(wǎng)址:http://weahome.cn/article/pddgse.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部