原文鏈接http://zhhll.icu/2020/12/04/%E6%A1%86%E6%9E%B6/hibernate/session%E6%8E%A5%E5%8F%A3/
session接口
Session接口是hibernate向應(yīng)用程序提供的操縱數(shù)據(jù)庫(kù)的最主要的接口眷唉,提供了保存肝陪、更新狼讨、刪除和加載Java對(duì)象的方法犬耻。
session具有一個(gè)緩存,位于緩存中的對(duì)象成為持久化對(duì)象排苍,和數(shù)據(jù)庫(kù)中的相關(guān)記錄對(duì)應(yīng)沦寂。session能夠在某些時(shí)間點(diǎn),按照緩存中對(duì)象的變化來(lái)執(zhí)行相關(guān)的SQL語(yǔ)句淘衙,來(lái)同步更新數(shù)據(jù)庫(kù)传藏,這一過(guò)程稱為刷新緩存(flush)。
hibernate把對(duì)象分為4種狀態(tài)彤守,持久化狀態(tài)毯侦,臨時(shí)狀態(tài),游離狀態(tài)具垫,刪除狀態(tài)侈离。session的特定方法可以使對(duì)象進(jìn)行狀態(tài)轉(zhuǎn)換
session緩存
session實(shí)例沒有結(jié)束生命周期,且沒有清理緩存筝蚕,則存放在session緩存中的對(duì)象也不會(huì)結(jié)束生命周期卦碾,session緩存可以減少訪問(wèn)數(shù)據(jù)庫(kù)的頻率。
操作session緩存
flush方法
緩存中對(duì)象同步到數(shù)據(jù)庫(kù)(會(huì)插入或更新數(shù)據(jù)庫(kù))起宽,使數(shù)據(jù)庫(kù)中的狀態(tài)與緩存中一致
注意:
session在以下情況下會(huì)刷新緩存
hibernate在事務(wù)提交之前會(huì)執(zhí)行flush()方法洲胖,然后再向數(shù)據(jù)庫(kù)提交事務(wù)
顯示調(diào)用session.flush()方法
在執(zhí)行HQL或者QBC查詢,會(huì)先進(jìn)行flush()操作坯沪,以得到數(shù)據(jù)表最新的記錄
refresh方法
將數(shù)據(jù)庫(kù)同步到緩存中(會(huì)查詢數(shù)據(jù)庫(kù))宾濒,使緩存中的狀態(tài)與數(shù)據(jù)庫(kù)一致
session.refresh();
clear方法
清理緩存,可以將session中的緩存清除
session.clear();
四種狀態(tài)的轉(zhuǎn)換
臨時(shí)狀態(tài)(Transient)
- 在使用代理主鍵的情況下屏箍,OID通常為null
- 不處于session緩存中
- 在數(shù)據(jù)庫(kù)中也沒有對(duì)應(yīng)的記錄
持久化狀態(tài)(Persist)
- OID不為null
- 位于session緩存中
- 若在數(shù)據(jù)庫(kù)中已經(jīng)有和其對(duì)應(yīng)的記錄,持久化對(duì)象和數(shù)據(jù)庫(kù)中的相關(guān)記錄對(duì)應(yīng)
- session在flush緩存時(shí)橘忱,會(huì)根據(jù)持久化對(duì)象的屬性變化赴魁,來(lái)同步數(shù)據(jù)庫(kù)
- 在同一個(gè)session實(shí)例的緩存中,數(shù)據(jù)庫(kù)表中每條記錄只對(duì)應(yīng)唯一的持久化對(duì)象
- 持久化對(duì)象的id不可以被修改钝诚,因?yàn)閔ibernate是根據(jù)id去進(jìn)行比較的
刪除狀態(tài)(Removed)
- 在數(shù)據(jù)庫(kù)中沒有和其OID對(duì)應(yīng)的記錄
- 不再處于session緩存中
游離狀態(tài)(Detached)
- OID不為null
- 不再處于session緩存中
- 一般情況下颖御,游離對(duì)象是由持久化對(duì)象轉(zhuǎn)變過(guò)來(lái)的,數(shù)據(jù)庫(kù)中可能還存在它對(duì)應(yīng)的記錄
save方法和persist方法的區(qū)別
在調(diào)用persist()方法時(shí)如果存在id,則會(huì)拋出異常潘拱,而save方法則可以正常執(zhí)行
org.hibernate.PersistentObjectException: detached entity passed to persist
get方法和load方法的區(qū)別
執(zhí)行g(shù)et方法會(huì)立即加載對(duì)象疹鳄,執(zhí)行l(wèi)oad方法若不使用該對(duì)象,則不會(huì)立即查詢芦岂,而是返回一個(gè)代理對(duì)象(延時(shí)加載)
-
若數(shù)據(jù)表中沒有對(duì)應(yīng)的記錄瘪弓,get方法返回null,load方法拋出異常
org.hibernate.ObjectNotFoundException: No row with the given identifier exists
-
load方法可能會(huì)拋出懶加載異常
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
注意:在session緩存中不能夠有兩個(gè)相同OID的對(duì)象禽最,否則會(huì)報(bào)異常
public static void testOid(Session session){
User user = (User) session.get(User.class,1);
System.out.println(user);
User user1 = new User();
user1.setId(1);
user1.setName("王五");
session.saveOrUpdate(user1);
}
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
evict方法
從session緩存中將指定的持久化對(duì)象移除
hibernate獲取原生JDBC連接進(jìn)行操作
可以使用doWork或者doReturnWork來(lái)使用原生JDBC操作數(shù)據(jù)
session.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
}
});
session.doReturningWork(new ReturningWork<Object>() {
@Override
public Object execute(Connection connection) throws SQLException {
return null;
}
});
由于本身的博客百度沒有收錄腺怯,博客地址http://zhhll.icu