Hibernate(三)通過 Session 操縱對象

一掩宜、首先新建一個項(xiàng)目

其他的與上一次的項(xiàng)目差不多相同砾赔,只不過date的改為java.util.date的

測試類中的修改如圖所示

刪除hibernate數(shù)據(jù)庫的所有表蝌箍,然后運(yùn)行該測試類,得到新的表暴心,表結(jié)構(gòu)如下:

二妓盲、Session 概述

(1)Session 接口是 Hibernate 向應(yīng)用程序提供的操縱數(shù)據(jù)庫的最主要的接口,它提供了基本的保存, 更新, 刪除和加載 Java 對象的方法专普。

(2)Session 具有一個緩存悯衬,位于緩存中的對象稱為持久化對象,它和數(shù)據(jù)庫中的相關(guān)記錄對應(yīng). Session 能夠在某些時(shí)間點(diǎn)檀夹,按照緩存中對象的變化來執(zhí)行相關(guān)的 SQL 語句筋粗,來同步更新數(shù)據(jù)庫, 這一過程被稱為刷新緩存(flush)。

(3)站在持久化的角度炸渡,Hibernate 把對象分為 4 種狀態(tài):持久化狀態(tài)娜亿,臨時(shí)狀態(tài),游離狀態(tài)蚌堵,刪除狀態(tài)买决。Session 的特定方法能使對象從一個狀態(tài)轉(zhuǎn)換到另一個狀態(tài)。

三吼畏、Session 緩存

(1)在 Session 接口的實(shí)現(xiàn)中包含一系列的 Java 集合, 這些 Java 集合構(gòu)成了 Session 緩存. 只要 Session 實(shí)例沒有結(jié)束生命周期, 且沒有清理緩存督赤,則存放在它緩存中的對象也不會結(jié)束生命周期。

(2)Session 緩存可減少 Hibernate 應(yīng)用程序訪問數(shù)據(jù)庫的頻率宫仗。

從上圖可以看出只發(fā)送一條sql够挂。

四、flush 緩存

(1)flush:Session 按照緩存中對象的屬性變化來同步更新數(shù)據(jù)庫藕夫。

(2)默認(rèn)情況下 Session 在以下時(shí)間點(diǎn)刷新緩存:

????①顯式調(diào)用 Session 的 flush() 方法孽糖。

????②當(dāng)應(yīng)用程序調(diào)用 Transaction 的 commit()方法時(shí), 該方法先 flush 枯冈,然后在向數(shù)據(jù)庫提交事務(wù)。

????③當(dāng)應(yīng)用程序執(zhí)行一些查詢(HQL, Criteria)操作時(shí)办悟,如果緩存中持久化對象的屬性已經(jīng)發(fā)生了變化尘奏,會先 flush 緩存,以保證查詢結(jié)果能夠反映持久化對象的最新狀態(tài)病蛉。

(3)flush 緩存的例外情況: 如果對象使用 native 生成器生成 OID炫加,那么當(dāng)調(diào)用 Session 的 save() 方法保存對象時(shí),會立即執(zhí)行向數(shù)據(jù)庫插入該實(shí)體的 insert 語句铺然。

(4)commit() 和 flush() 方法的區(qū)別:flush 執(zhí)行一系列 sql 語句俗孝,但不提交事務(wù);commit 方法先調(diào)用flush() 方法魄健,然后提交事務(wù)赋铝。提交事務(wù)意味著對數(shù)據(jù)庫操作永久保存下來。

五沽瘦、設(shè)定刷新緩存的時(shí)間點(diǎn)

若希望改變 flush 的默認(rèn)時(shí)間點(diǎn), 可以通過 Session 的 setFlushMode() 方法顯式設(shè)定 flush 的時(shí)間點(diǎn) 革骨。

知識點(diǎn)擴(kuò)展:Hibernate的FlushMode與session.flush()

Hibernate session FlushMode有五種屬性:

1、NEVEL:已經(jīng)廢棄了析恋,被MANUAL取代了

2良哲、MANUAL:

如果FlushMode是MANUAL或NEVEL,在操作過程中hibernate會將事務(wù)設(shè)置為readonly,所以在增加助隧、刪除或修改操作過程中會出現(xiàn)如下錯誤org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition筑凫;

解決辦法:配置事務(wù),spring會讀取事務(wù)中的各種配置來覆蓋hibernate的session中的FlushMode喇颁;

3漏健、AUTO

設(shè)置成auto之后,當(dāng)程序進(jìn)行查詢橘霎、提交事務(wù)或者調(diào)用session.flush()的時(shí)候,都會使緩存和數(shù)據(jù)庫進(jìn)行同步殖属,也就是刷新數(shù)據(jù)庫

4姐叁、COMMIT

提交事務(wù)或者session.flush()時(shí),刷新數(shù)據(jù)庫洗显;查詢不刷新

5外潜、ALWAYS:

每次進(jìn)行查詢、提交事務(wù)挠唆、session.flush()的時(shí)候都會刷數(shù)據(jù)庫

ALWAYS和AUTO的區(qū)別:當(dāng)hibernate緩存中的對象被改動之后处窥,會被標(biāo)記為臟數(shù)據(jù)(即與數(shù)據(jù)庫不同步了)。當(dāng) session設(shè)置為FlushMode.AUTO時(shí)玄组,hibernate在進(jìn)行查詢的時(shí)候會判斷緩存中的數(shù)據(jù)是否為臟數(shù)據(jù)滔驾,是則刷數(shù)據(jù)庫谒麦,不是則不刷,而always是直接刷新哆致,不進(jìn)行任何判斷绕德。很顯然auto比always要高效得多。

六摊阀、數(shù)據(jù)庫的隔離級別

(1)對于同時(shí)運(yùn)行的多個事務(wù)耻蛇,當(dāng)這些事務(wù)訪問數(shù)據(jù)庫中相同的數(shù)據(jù)時(shí),如果沒有采取必要的隔離機(jī)制胞此,就會導(dǎo)致各種并發(fā)問題:

臟讀:對于兩個事物 T1臣咖、T2,T1 讀取了已經(jīng)被 T2 更新但還沒有被提交的字段漱牵。之后亡哄,若 T2 回滾,T1讀取的內(nèi)容就是臨時(shí)且無效的布疙。

不可重復(fù)讀:對于兩個事物 T1蚊惯、 T2,T1 讀取了一個字段灵临,然后 T2 更新了該字段截型。之后,T1再次讀取同一個字段儒溉,值就不同了宦焦。

幻讀:對于兩個事物 T1、T2顿涣,T1 從一個表中讀取了一個字段波闹,然后 T2 在該表中插入了一些新的行。之后涛碑,如果 T1 再次讀取同一個表精堕,就會多出幾行。

(2)數(shù)據(jù)庫事務(wù)的隔離性:數(shù)據(jù)庫系統(tǒng)必須具有隔離并發(fā)運(yùn)行各個事務(wù)的能力蒲障,使它們不會相互影響歹篓,避免各種并發(fā)問題。

(3)一個事務(wù)與其他事務(wù)隔離的程度稱為隔離級別揉阎。數(shù)據(jù)庫規(guī)定了多種事務(wù)隔離級別庄撮,不同隔離級別對應(yīng)不同的干擾程度,隔離級別越高毙籽,數(shù)據(jù)一致性就越好洞斯,但并發(fā)性越弱。

(4)數(shù)據(jù)庫提供的 4 種事務(wù)隔離級別:

Oracle 支持的 2 種事務(wù)隔離級別:READ COMMITED, SERIALIZABLE坑赡。Oracle 默認(rèn)的事務(wù)隔離級別為:READ COMMITED

Mysql 支持 4 中事務(wù)隔離級別. Mysql 默認(rèn)的事務(wù)隔離級別為:REPEATABLE READ

七烙如、在 MySql 中設(shè)置隔離級別

(1)每啟動一個 mysql 程序么抗,就會獲得一個單獨(dú)的數(shù)據(jù)庫連接。每個數(shù)據(jù)庫連接都有一個全局變量 @@tx_isolation厅翔,表示當(dāng)前的事務(wù)隔離級別乖坠。MySQL 默認(rèn)的隔離級別為 Repeatable Read。

(2)查看當(dāng)前的隔離級別: SELECT @@tx_isolation;

(3)設(shè)置當(dāng)前 mySQL 連接的隔離級別:

set transaction isolation level read committed;

(4)設(shè)置數(shù)據(jù)庫系統(tǒng)的全局的隔離級別:

set global transaction isolation level read committed;

八刀闷、在 Hibernate 中設(shè)置隔離級別

(1)JDBC 數(shù)據(jù)庫連接使用數(shù)據(jù)庫系統(tǒng)默認(rèn)的隔離級別熊泵。 在 Hibernate 的配置文件中可以顯式的設(shè)置隔離級別。每一個隔離級別都對應(yīng)一個整數(shù):

***1. READ UNCOMMITED

***2. READ COMMITED

***4. REPEATABLE READ

***8. SERIALIZEABLE

(2)Hibernate 通過為 Hibernate 映射文件指定 hibernate.connection.isolation 屬性來設(shè)置事務(wù)的隔離級別甸昏。

九减江、reflesh()和hibernate的事務(wù)隔離級別的例子

(1)打斷點(diǎn)先打印一次

(2)修改數(shù)據(jù)庫

(3)運(yùn)行完曼验,打印結(jié)果一樣,author沒變

(4)設(shè)置hibernate的事務(wù)隔離級別

(5)重新運(yùn)行該方法

(6)修改數(shù)據(jù)庫的AUTHOR為SUN

(7)運(yùn)行結(jié)束,最后的打印是最新的

十炕倘、持久化對象的狀態(tài)

站在持久化的角度喧锦,Hibernate 把對象分為 4 種狀態(tài):持久化狀態(tài)辆童、臨時(shí)狀態(tài)抒痒、游離狀態(tài)、刪除狀態(tài)修械;Session 的特定方法能使對象從一個狀態(tài)轉(zhuǎn)換到另一個狀態(tài)趾牧。

(1)臨時(shí)對象(Transient):

在使用代理主鍵的情況下, OID 通常為 null

不處于 Session 的緩存中

在數(shù)據(jù)庫中沒有對應(yīng)的記錄

(2)持久化對象(也叫”托管”)(Persist):

OID 不為 null

位于 Session 緩存中

若在數(shù)據(jù)庫中已經(jīng)有和其對應(yīng)的記錄, 持久化對象和數(shù)據(jù)庫中的相關(guān)記錄對應(yīng)

Session 在 flush 緩存時(shí), 會根據(jù)持久化對象的屬性變化, 來同步更新數(shù)據(jù)庫

在同一個 Session 實(shí)例的緩存中, 數(shù)據(jù)庫表中的每條記錄只對應(yīng)唯一的持久化對象

(3)刪除對象(Removed)

在數(shù)據(jù)庫中沒有和其 OID 對應(yīng)的記錄

不再處于 Session 緩存中

一般情況下, 應(yīng)用程序不該再使用被刪除的對象

(4)游離對象(也叫”脫管”) (Detached):

OID 不為 null

不再處于 Session 緩存中

一般情況需下, 游離對象是由持久化對象轉(zhuǎn)變過來的, 因此在數(shù)據(jù)庫中可能還存在與它對應(yīng)的記錄

十一、對象的狀態(tài)轉(zhuǎn)換圖

十一肯污、Session 的 save() 方法

(1)Session 的 save() 方法使一個臨時(shí)對象轉(zhuǎn)變?yōu)槌志没瘜ο?/p>

(2)Session 的 save() 方法完成以下操作:

把 News 對象加入到 Session 緩存中, 使它進(jìn)入持久化狀態(tài)

選用映射文件指定的標(biāo)識符生成器, 為持久化對象分配唯一的 OID. 在 使用代理主鍵的情況下, setId() 方法為 News 對象設(shè)置 OID 是無效的.

計(jì)劃執(zhí)行一條 insert 語句:在 flush 緩存的時(shí)候

(2)Hibernate 通過持久化對象的 OID 來維持它和數(shù)據(jù)庫相關(guān)記錄的對應(yīng)關(guān)系翘单。當(dāng) News 對象處于持久化狀態(tài)時(shí), 不允許程序隨意修改它的 ID。

(3)persist() 和 save() 區(qū)別:

當(dāng)對一個 OID 不為 Null 的對象執(zhí)行 save() 方法時(shí), 會把該對象以一個新的 oid 保存到數(shù)據(jù)庫中;? 但執(zhí)行 persist() 方法時(shí)會拋出一個異常:蹦渣。

案例:

(1)先把該對象的主鍵生成方式改為hilo

(2)編寫測試

(3)設(shè)置ID是無效的

(4)當(dāng) News 對象處于持久化狀態(tài)時(shí), 不允許程序隨意修改它的 ID

(5)peisist方法

十二哄芜、Session 的 get() 和 load() 方法

(1)都可以根據(jù)跟定的 OID 從數(shù)據(jù)庫中加載一個持久化對象

(2)區(qū)別:

當(dāng)數(shù)據(jù)庫中不存在與 OID 對應(yīng)的記錄時(shí), load() 方法拋出 ObjectNotFoundException 異常, 而 get() 方法返回 null;

兩者采用不同的延遲檢索策略:load 方法支持延遲加載策略柬唯。而 get 不支持认臊。

(3)執(zhí)行g(shù)et()方法:會立即加載對象;執(zhí)行l(wèi)oad方法:若不使用該對象权逗,則不會立即執(zhí)行查詢操作美尸,而返回一個代理對象。

(4)若數(shù)據(jù)庫中沒有對應(yīng)記錄斟薇,且Session也沒有被關(guān)閉,get返回Null恕酸;load若不使用該對象的任何屬性堪滨,沒問題,若需要初始化了蕊温,拋出異常袱箱。

(5)load方法可能會拋出懶加載異常:在需要初始化代理對象之前已經(jīng)關(guān)閉了Session

十三遏乔、Session 的 update() 方法

(1)Session 的 update() 方法使一個游離對象轉(zhuǎn)變?yōu)槌志没瘜ο螅⑶矣?jì)劃執(zhí)行一條 update 語句发笔。若希望 Session 僅當(dāng)修改了 News 對象的屬性時(shí)盟萨,才執(zhí)行 update() 語句,可以把映射文件中 元素的 select-before-update 設(shè)為 true了讨,該屬性的默認(rèn)值為 false捻激。

(2)當(dāng) update() 方法關(guān)聯(lián)一個游離對象時(shí), 如果在 Session 的緩存中已經(jīng)存在相同 OID 的持久化對象, 會拋出異常。

(3)當(dāng) update() 方法關(guān)聯(lián)一個游離對象時(shí), 如果在數(shù)據(jù)庫中不存在相應(yīng)的記錄前计,也會拋出異常胞谭。.

示例:

①、若更新一個持久化對象男杈,不需要顯示的調(diào)用update方法丈屹,因?yàn)檎{(diào)用Transaction的commot方法時(shí),會執(zhí)行session的flush方法伶棒。

十四旺垒、Session 的 saveOrUpdate() 方法

Session 的 saveOrUpdate() 方法同時(shí)包含了 save() 與 update() 方法的功能。

判定對象為臨時(shí)對象的標(biāo)準(zhǔn):

①肤无、Java 對象的 OID 為 null先蒋;

②、映射文件中為 設(shè)置了 unsaved-value 屬性, 并且 Java 對象的 OID 取值與這個 unsaved-value 屬性值匹配舅锄。

(1)執(zhí)行insert語句

(2)若OID不為空鞭达,但數(shù)據(jù)表還沒有和其對應(yīng)的記錄,會拋出一個異常皇忿;如果有其對應(yīng)的記錄畴蹭,則更新。

十五鳍烁、Session 的 delete() 方法

(1)Session 的 delete() 方法既可以刪除一個游離對象, 也可以刪除一個持久化對象叨襟;

(2)Session 的 delete() 方法處理過程:

①、計(jì)劃執(zhí)行一條 delete 語句幔荒;

②糊闽、把對象從 Session 緩存中刪除,該對象進(jìn)入刪除狀態(tài)爹梁。

(3)Hibernate 的 cfg.xml 配置文件中有一個 hibernate.use_identifier_rollback 屬性, 其默認(rèn)值為 false, 若把它設(shè)為 true, 將改變 delete() 方法的運(yùn)行行為:delete() 方法會把持久化對象或游離對象的 OID 設(shè)置為 null右犹,使它們變?yōu)榕R時(shí)對象。

示例1:

示例2:

示例3:

十六姚垃、Session 的 evict() 方法

從session緩存中把指定的持久化對象移除念链。

十七、通過 Hibernate 調(diào)用存儲過程

(1)Work 接口:直接通過 JDBC API 來訪問數(shù)據(jù)庫的操作;

(2)Session 的 doWork(Work) 方法用于執(zhí)行 Work 對象指定的操作掂墓,即調(diào)用 Work 對象的 execute() 方法谦纱。Session 會把當(dāng)前使用的數(shù)據(jù)庫連接傳遞給 execute() 方法。

十八君编、Hibernate 與觸發(fā)器協(xié)同工作

(1)Hibernate 與數(shù)據(jù)庫中的觸發(fā)器協(xié)同工作時(shí)跨嘉,會造成兩類問題:

①、觸發(fā)器使 Session 的緩存中的持久化對象與數(shù)據(jù)庫中對應(yīng)的數(shù)據(jù)不一致:觸發(fā)器運(yùn)行在數(shù)據(jù)庫中, 它執(zhí)行的操作對 Session 是透明的吃嘿;

②祠乃、Session 的 update() 方法盲目地激發(fā)觸發(fā)器: 無論游離對象的屬性是否發(fā)生變化, 都會執(zhí)行 update 語句, 而 update 語句會激發(fā)數(shù)據(jù)庫中相應(yīng)的觸發(fā)器。

(2)解決方案

①唠椭、在執(zhí)行完 Session 的相關(guān)操作后跳纳,立即調(diào)用 Session 的 flush() 和 refresh() 方法,迫使 Session 的緩存與數(shù)據(jù)庫同步(refresh() 方法重新從數(shù)據(jù)庫中加載對象)贪嫂。

②寺庄、在映射文件的的 元素中設(shè)置 select-before-update 屬性:當(dāng) Session 的 update 或 saveOrUpdate() 方法更新一個游離對象時(shí),會先執(zhí)行 Select 語句力崇,獲得當(dāng)前游離對象在數(shù)據(jù)庫中的最新數(shù)據(jù), 只有在不一致的情況下才會執(zhí)行 update 語句斗塘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亮靴,隨后出現(xiàn)的幾起案子馍盟,更是在濱河造成了極大的恐慌,老刑警劉巖茧吊,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贞岭,死亡現(xiàn)場離奇詭異,居然都是意外死亡搓侄,警方通過查閱死者的電腦和手機(jī)瞄桨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讶踪,“玉大人芯侥,你說我怎么就攤上這事∪榧ィ” “怎么了柱查?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長云石。 經(jīng)常有香客問我唉工,道長,這世上最難降的妖魔是什么汹忠? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任酵紫,我火速辦了婚禮告嘲,結(jié)果婚禮上错维,老公的妹妹穿的比我還像新娘奖地。我一直安慰自己,他們只是感情好赋焕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布参歹。 她就那樣靜靜地躺著,像睡著了一般隆判。 火紅的嫁衣襯著肌膚如雪犬庇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天侨嘀,我揣著相機(jī)與錄音臭挽,去河邊找鬼。 笑死咬腕,一個胖子當(dāng)著我的面吹牛欢峰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涨共,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼纽帖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了举反?” 一聲冷哼從身側(cè)響起懊直,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎火鼻,沒想到半個月后室囊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡魁索,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年融撞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛾默。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡懦铺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出支鸡,到底是詐尸還是另有隱情冬念,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布牧挣,位于F島的核電站急前,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瀑构。R本人自食惡果不足惜裆针,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一刨摩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧世吨,春花似錦澡刹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沐祷,卻和暖如春嚷闭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赖临。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工胞锰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兢榨。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓嗅榕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親色乾。 傳聞我的和親對象是個殘疾皇子誊册,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容