日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一篇读懂--mybatis的缓存

發(fā)布時(shí)間:2025/3/12 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一篇读懂--mybatis的缓存 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一篇讀懂–mybatis的緩存

MyBatis的緩存指的是緩存查詢結(jié)果,當(dāng)以后使用相同的sql語句、傳入相同的參數(shù)進(jìn)行查詢時(shí),可直接從mybatis本地緩存中獲取查詢結(jié)果,而不必查詢數(shù)據(jù)庫。

mybatis的緩存包括一級(jí)緩存、二級(jí)緩存,一級(jí)緩存默認(rèn)是開啟的,二級(jí)緩存默認(rèn)是關(guān)閉的。

一級(jí)緩存:

SqlSession級(jí)別:在SqlSession中有一個(gè)Map,key是由sql語句、參數(shù)等信息組成的唯一值,value是查詢出來的結(jié)果對(duì)象。
好處: 減小數(shù)據(jù)庫壓力
如何失效 :只要此sqlSession調(diào)用了、、這些會(huì)修改數(shù)據(jù)庫的元素,就會(huì)清空此sqlSession的一級(jí)緩存,不管有沒有使用commit()提交。
舉例:

User user1 = mapper.queryUserById(1);User user2 = mapper.queryUserById(1);

第一次查詢時(shí),就將查詢結(jié)果放到一級(jí)緩存中。
如果后續(xù)使用的sql語句相同、傳入的實(shí)參也相同,則結(jié)果對(duì)象也會(huì)相同,直接從一級(jí)緩存中獲取結(jié)果對(duì)象,不再查詢數(shù)據(jù)庫。

User user1 = mapper.queryUserById(1);sqlSession.commit();User user2 = mapper.queryUserById(1);

如果此sqlSession調(diào)用了commit()方法,會(huì)自動(dòng)清空此sqlSession的一級(jí)緩存。
因?yàn)槭褂胏ommit(),會(huì)將修改提交到數(shù)據(jù)庫,下一次相同的查詢,查詢結(jié)果可能變了,之前的一級(jí)緩存不能再用,所以會(huì)自動(dòng)清空。

下面用spring整合mybatis來測試一下mybatis的一級(jí)緩存:
1、下面是service層實(shí)現(xiàn), 可以看到,我兩次查詢了同一個(gè)數(shù)據(jù),理論上由于mybatis中默認(rèn)開啟一級(jí)緩存, 那么第二次肯定時(shí)要從緩存中獲取,而不是創(chuàng)建SqlSession對(duì)象重新從數(shù)據(jù)庫獲取:

@Autowired private LsjmUserMapper lsjmUserMapper;@Override public LsjmUser getUser() {// 第一次查詢LsjmUser user = lsjmUserMapper.getUserByName("300");System.out.println(user.toString());// 第二次查詢LsjmUser user1 = lsjmUserMapper.getUserByName("300");System.out.println(user1.toString());return user; }

從日志信息可以很明顯的看到,代碼中的兩次查詢構(gòu)建了兩個(gè)SqlSession對(duì)象,也就是說第二次查詢并沒有從前一次的SqlSession緩存中獲取,而是自己新建一個(gè)SQLSession對(duì)象,重新查詢;這樣看來,一級(jí)緩存好像失效了?

這是為什么呢?因?yàn)槲覀儧]有加@Transaction注解
spring 中 結(jié)合 mybatis中,默認(rèn)情況下,數(shù)據(jù)庫處于自動(dòng)提交模式,每一條sql語句處于一個(gè)單獨(dú)的事務(wù)中,語句執(zhí)行完畢時(shí),如果執(zhí)行成功則隱式提交事務(wù)。而mybatis的一級(jí)緩存在這種情況下是無效的,想要一級(jí)緩存起作用,則要開啟事務(wù):

開啟事務(wù): spring使用ThreadLocal獲取當(dāng)前資源綁定同一個(gè)SQLSession

未開啟事務(wù):每次查詢,spring關(guān)閉舊的SslSession,創(chuàng)建一個(gè)新的Sqlsession對(duì)象,一級(jí)緩存補(bǔ)氣作用

還有一種特殊情況,也會(huì)調(diào)用到緩存:

ProcessDef list = processMapper.selectByPrimaryKey(5L);list.setCode("123");ProcessDef list1 = processMapper.selectByPrimaryKey(5L);

(注意,上面這個(gè)方法要加上@Transaction注解)
像上面這種情況,有時(shí)候在代碼中也會(huì)出現(xiàn),然后你就會(huì)找bug找半天都找不出問題;
結(jié)果是:list1的結(jié)果中的Code字段是“123”,而不是數(shù)據(jù)庫中的那個(gè)字段!是不是不可思議,你可以自己在本地試試,事實(shí)就是如此。
原因是什么呢? 上面第一次查詢直接去數(shù)據(jù)庫查,這個(gè)可以理解, list.setCode(“123”);之后,第一次查詢出來的緩存就已經(jīng)變了,其中code字段就變成123了,所以這也是list1中code字段為123的原因!(這種情況大家要留意一下,搞了我半天的時(shí)間去找bug)
二級(jí)緩存:
mapper級(jí)別,同一個(gè)namespace下的mapper,有一個(gè)Map。

SqlSession sqlSession1 = MyBatisUtils.getSqlSession();UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);User user1 = mapper1.queryUserById(1);System.out.println(user1);SqlSession sqlSession2 = MyBatisUtils.getSqlSession();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);User user2 = mapper2.queryUserById(1);System.out.println(user2);

不使用二級(jí)緩存,會(huì)執(zhí)行2次查詢。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的一篇读懂--mybatis的缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。