Hibernate Session

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

Session具有一個具體的緩存,位于緩存中的對象稱為持久化對象宪塔。它和數(shù)據(jù)庫中的記錄對應(yīng)。Session可以在某些時間點比搭,按照緩存中的對象變化來執(zhí)行相應(yīng)的SQL語句南誊,同步更新數(shù)據(jù)庫,這一過程稱為刷新緩存(flush)抄囚。

站在持久化的角度將Hibernate分為四種狀態(tài):

  • 持久化狀態(tài)
  • 臨時狀態(tài)
  • 游離狀態(tài)
  • 刪除狀態(tài)

Session中的特定方法能使對象從一個狀態(tài)轉(zhuǎn)為另一個狀態(tài)。

Session緩存

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

Session緩存可以減少Hibernate應(yīng)用程序訪問數(shù)據(jù)庫的次數(shù)谦屑。

HelloWorld helloWorld = this.session.get(HelloWorld.class, 1);
HelloWorld helloWorld2 = this.session.get(HelloWorld.class, 1);

這兩條查詢只會使用一次SQL語句劲室。


HelloWorld helloWorld = session.get(HelloWorld.class, 1);
helloWorld.setTitle("Today");

當(dāng)我們使用set方法是自動更新到了數(shù)據(jù)庫。查看控制臺我們會發(fā)現(xiàn)程序?qū)嶋H上調(diào)用了SQL語句充蓝。此時會自動調(diào)用flush方法喉磁。

flush緩存

flush的作用:使數(shù)據(jù)庫中的對象與Session中的對象保持一致。為了保持一致协怒,則可能發(fā)送SQL語句。

在調(diào)用commit方法時仑撞,會先進行flush,然后再提交事務(wù)隧哮。

在Transaction的commit方法中,先調(diào)用session的flush方法陨帆,再提交事務(wù)采蚀。

flush方法可能會發(fā)送SQL語句。不會提交事務(wù)。

注意:在未提交事務(wù)或者顯示的調(diào)用session.flush()方法之前春霍,也有可能會進行flush操作。

  1. 執(zhí)行HQL或者QBC查詢。會先進行flush操作,得到數(shù)據(jù)表最新的記錄。
  2. 若數(shù)據(jù)記錄的ID是由底層數(shù)據(jù)庫使用自增的方式生成的灾螃,則在調(diào)用save方法后就會立即發(fā)送insert語句。因為save方法必須保證對象的ID是存在的嵌赠。

commit和flush方法的區(qū)別:flush執(zhí)行一系列的SQL語句熄赡,但不提交事務(wù)。commit方法會先調(diào)用flush方法彼硫,然后提交事務(wù)。意味著提交事務(wù)那么數(shù)據(jù)庫操作就被永久的保存下來词渤。

refresh

緩存中的數(shù)據(jù)是最新的狀態(tài)串绩。調(diào)用這個方法會強制發(fā)送一條select語句得到記錄的最新狀態(tài)缺虐。

refresh會強制發(fā)送select語句礁凡,使session緩存中的對象的狀態(tài)和數(shù)據(jù)表中對應(yīng)的記錄保持一致。

操作Session緩存

持久化對象

  • 臨時對象(Transient)
    在使用代理主鍵的情況下腰涧,OID通常為null紊浩。
    不處于Session緩存中疗锐。
    在數(shù)據(jù)庫中沒有對應(yīng)的記錄。

  • 持久化對象(Persist)
    持久化對象也叫托管滑臊。
    OID不為null。
    位于Session緩存中雇卷。
    若在數(shù)據(jù)庫中已經(jīng)有和其對應(yīng)的記錄,持久化對象和數(shù)據(jù)庫中相關(guān)的記錄對應(yīng)小染。
    Session在flush緩存時贮折,會根據(jù)持久化對象的屬性變化,來同步更新數(shù)據(jù)庫调榄。
    在同一個Session實例的緩存中,數(shù)據(jù)庫表中的每條記錄只對應(yīng)唯一的持久化對象筐带。

  • 刪除對象(Removed)
    在數(shù)據(jù)庫中沒有和其OID對應(yīng)的記錄缤灵。
    不再處于Session的緩存中。
    一般情況下凤价,應(yīng)用程序不該再使用被刪除的對象。

  • 游離對象(Detached)
    也叫托管富蓄。
    OID不為null慢逾。
    不再處于Session緩存中灭红。
    一般情況下口注,游離對象是從持久化對象轉(zhuǎn)變過來的。因此在數(shù)據(jù)庫中可能還存在與它對應(yīng)的記錄寝志。

    對象狀態(tài)轉(zhuǎn)換圖

Session持久化操作的方法

首先說一個概念OID材部。Hibernate通過持久化對象的OID來維持它和數(shù)據(jù)庫相關(guān)記錄的對應(yīng)關(guān)系。當(dāng)News對象處于持久化狀態(tài)時乐导,不允許程序隨意修改它的Id

save()方法:

  1. 使一個臨時對象變?yōu)橐粋€持久化對象旺拉。
  2. 為對象分配Id。
  3. 在flush緩存時會發(fā)送一條insert語句蛾狗。
  4. 在save方法之前的Id是無效的泽本。
  5. 持久化對象的Id是不能被修改的。

persist()方法:

  1. 也會執(zhí)行insert操作规丽。
  2. 如果在persist方法之前有Id了,則不會執(zhí)行insert操作冰抢,而是拋出一個異常艘狭。

get和load的區(qū)別:

  1. 執(zhí)行g(shù)et方法會立即加載對象,而執(zhí)行l(wèi)oad方法巢音,若不使用該對象。則不會立即執(zhí)行查詢操作梧躺,而返回一個代理對象傲绣。get立即查詢巩踏。load延遲加載续搀。
  2. 如果在數(shù)據(jù)庫中沒有對應(yīng)的記錄。Session沒有被關(guān)閉禁舷,同時需要使用對象時,get會返回一個空值(null)在讶,load則會拋出一個異常霜大。
  3. load方法可能會拋出懶加載異常(LazyInitializationException)革答。在需要初始化代理對象之前已經(jīng)關(guān)閉了Session。

update方法:

  1. 若更新一個持久化對象残拐,則不需要顯式的調(diào)用update方法。因為在調(diào)用transaction的commit方法時會先執(zhí)行Session的flush方法囊卜。
  2. 更新一個游離對象時错沃,需要顯示的調(diào)用Session的update方法。同時可以將一個游離對象變?yōu)橐粋€持久化對象枢析。

注意:

  1. 無論要更新的游離對象與數(shù)據(jù)包中的記錄是否一致,都會發(fā)送Update語句司浪。
    如何讓update方法不盲目的觸發(fā)Update語句:
    在*.hbm.xml文件的class結(jié)點設(shè)置一個屬性select-before-update=true把沼。通常不需要設(shè)置該屬性。

  2. 若數(shù)據(jù)表中沒有對應(yīng)的記錄饮睬,但還是調(diào)用了update方法則會拋出異常。

  3. 若在Session緩存中存在相同的OID的持久化對象垦垂,則會拋出異常。因為在同一個Session的緩存中不能有兩個Id相同的對象劫拗。

saveOrUpdate方法:

saveOrUpdate方法同時包含了save方法和update方法的功能。



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

  • Java對象的OID是否為null憔足。
  • 映射文件中<id>設(shè)置了unsaved-value屬性酒繁。并且Java對象的OID取值和這個unsaved-value屬性相匹配。

若OID不為空揭绑,但數(shù)據(jù)表中還沒有和其對應(yīng)的記錄郎哭,會拋出一個異常他匪。
OID的值等于ID的unsaved-value屬性值的對象夸研,也被認(rèn)為是一個游離對象。

delete方法

執(zhí)行刪除操作悼沈。只要OID和數(shù)據(jù)表中的一條記錄對應(yīng)姐扮,就會執(zhí)行delete操作。如果沒有對應(yīng)的記錄則拋出異常溶握。

可以通過設(shè)置Hibernate配置文件的屬性hibernate.use_identifier_rollback為true使刪除對象后把其OID置為null。

evict方法

從Session緩存中把指定的持久化對象移除萍肆。

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

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

Hibernate與觸發(fā)器協(xié)同工作

Hibernate與觸發(fā)器協(xié)同工作時會造成兩個問題:

  1. 觸發(fā)器使Session緩存中的持久化對象與數(shù)據(jù)庫中對應(yīng)的數(shù)據(jù)不一致。觸發(fā)器在數(shù)據(jù)庫中操作奖蔓,它執(zhí)行的操作對于Session是透明的。
  2. Session的update方法盲目的觸發(fā)觸發(fā)器厨疙。無論游離對象的屬性是否發(fā)生變化都會執(zhí)行update語句疑务。而update語句會觸發(fā)數(shù)據(jù)庫中相應(yīng)的觸發(fā)器。

解決方案

  1. 在執(zhí)行完Session的相關(guān)操作后知允,立即調(diào)用Session的flush和refresh方法。迫使Session緩存和數(shù)據(jù)庫的數(shù)據(jù)同步保屯。方法重新從數(shù)據(jù)庫中加載數(shù)據(jù)涤垫。
  2. 在映射文件的<class>元素中設(shè)置select-before-update屬性。當(dāng)Session的update或saveOrUpdate方法更新一個游離對象時雹姊,先執(zhí)行select語句獲取該游離對象在數(shù)據(jù)庫中的最新數(shù)據(jù)衡楞。只有在不一致的情況下才會執(zhí)行update操作。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歧杏,一起剝皮案震驚了整個濱河市迷守,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兑凿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咐鹤,死亡現(xiàn)場離奇詭異圣絮,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門凡涩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疹蛉,“玉大人,你說我怎么就攤上這事讹蘑≈耍” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵翠拣,是天一觀的道長。 經(jīng)常有香客問我蛮粮,道長谜慌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任变泄,我火速辦了婚禮,結(jié)果婚禮上妨蛹,老公的妹妹穿的比我還像新娘晴竞。我一直安慰自己,他們只是感情好噩死,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布已维。 她就那樣靜靜地躺著,像睡著了一般衣摩。 火紅的嫁衣襯著肌膚如雪捂敌。 梳的紋絲不亂的頭發(fā)上既琴,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音逆济,去河邊找鬼磺箕。 笑死奖慌,一個胖子當(dāng)著我的面吹牛松靡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岛马,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼屠列,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了夏志?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盲镶,失蹤者是張志新(化名)和其女友劉穎蝌诡,沒想到半個月后枫吧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡颁湖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年例隆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镰禾。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吴侦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情劫樟,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布叠艳,位于F島的核電站易阳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏翅睛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一捕发、第九天 我趴在偏房一處隱蔽的房頂上張望很魂。 院中可真熱鬧,春花似錦法挨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至葛超,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绣张,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工沼撕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人好芭。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓冲呢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敬拓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

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