Mybatis 为什么不要用二级缓存
https://www.cnblogs.com/liouwei4083/p/6025929.html
mybatis 二級(jí)緩存不推薦使用
一 mybatis的緩存使用。
大體就是首先根據(jù)你的sqlid,參數(shù)的信息自己算出一個(gè)key值,然后你查詢的時(shí)候,會(huì)先把這個(gè)key值去緩存中找看有沒(méi)有value,如果有,直接返回出來(lái),就不查詢db了。如果沒(méi)有,那么查詢db,然后將key,value保存到緩存中,以便下次使用。
1.1mybatis的一級(jí)緩存是基于sqlsession為生命周期的
當(dāng)你這個(gè)session沒(méi)有了,緩存就沒(méi)有了,其次當(dāng)你sql執(zhí)行!isselect語(yǔ)句的時(shí)候,緩存也會(huì)被直接全部清理掉以保證數(shù)據(jù)一致性。
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
//清理緩存
clearLocalCache();
return doUpdate(ms, parameter);
}
1.2 mybatis的二級(jí)緩存是基于application為生命周期的
范圍是按照每個(gè)namepace一個(gè)緩存來(lái)存貯和維護(hù),同一個(gè)namespace放到一個(gè)緩存對(duì)象中,當(dāng)這個(gè)namaspace中執(zhí)行了!isselect語(yǔ)句的時(shí)候,整個(gè)namespace中的緩存全部清除掉。
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
//清理緩存,并且!isselect語(yǔ)句的flushcache都是默認(rèn)為true的。
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}
以下摘抄自網(wǎng)絡(luò)觀點(diǎn)文字 http://blog.csdn.net/isea533/article/details/44566257
三、Cache使用時(shí)的注意事項(xiàng)
1. 只能在【只有單表操作】的表上使用緩存
不只是要保證這個(gè)表在整個(gè)系統(tǒng)中只有單表操作,而且和該表有關(guān)的全部操作必須全部在一個(gè)namespace下。
2. 在可以保證查詢遠(yuǎn)遠(yuǎn)大于insert,update,delete操作的情況下使用緩存
這一點(diǎn)不需要多說(shuō),所有人都應(yīng)該清楚。記住,這一點(diǎn)需要保證在1的前提下才可以!
四、避免使用二級(jí)緩存
可能會(huì)有很多人不理解這里,二級(jí)緩存帶來(lái)的好處遠(yuǎn)遠(yuǎn)比不上他所隱藏的危害。
緩存是以namespace為單位的,不同namespace下的操作互不影響。
insert,update,delete操作會(huì)清空所在namespace下的全部緩存。
通常使用MyBatis Generator生成的代碼中,都是各個(gè)表獨(dú)立的,每個(gè)表都有自己的namespace。
為什么避免使用二級(jí)緩存
在符合【Cache使用時(shí)的注意事項(xiàng)】的要求時(shí),并沒(méi)有什么危害。
其他情況就會(huì)有很多危害了。
針對(duì)一個(gè)表的某些操作不在他獨(dú)立的namespace下進(jìn)行。
例如在UserMapper.xml中有大多數(shù)針對(duì)user表的操作。但是在一個(gè)XXXMapper.xml中,還有針對(duì)user單表的操作。
這會(huì)導(dǎo)致user在兩個(gè)命名空間下的數(shù)據(jù)不一致。如果在UserMapper.xml中做了刷新緩存的操作,在XXXMapper.xml中緩存仍然有效,如果有針對(duì)user的單表查詢,使用緩存的結(jié)果可能會(huì)不正確。
更危險(xiǎn)的情況是在XXXMapper.xml做了insert,update,delete操作時(shí),會(huì)導(dǎo)致UserMapper.xml中的各種操作充滿未知和風(fēng)險(xiǎn)。
有關(guān)這樣單表的操作可能不常見(jiàn)。但是你也許想到了一種常見(jiàn)的情況。
多表操作一定不能使用緩存
為什么不能?
首先不管多表操作寫(xiě)到那個(gè)namespace下,都會(huì)存在某個(gè)表不在這個(gè)namespace下的情況。
例如兩個(gè)表:role和user_role,如果我想查詢出某個(gè)用戶的全部角色role,就一定會(huì)涉及到多表的操作。
<select id="selectUserRoles" resultType="UserRoleVO">
select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>
像上面這個(gè)查詢,你會(huì)寫(xiě)到那個(gè)xml中呢??
不管是寫(xiě)到RoleMapper.xml還是UserRoleMapper.xml,或者是一個(gè)獨(dú)立的XxxMapper.xml中。如果使用了二級(jí)緩存,都會(huì)導(dǎo)致上面這個(gè)查詢結(jié)果可能不正確。
如果你正好修改了這個(gè)用戶的角色,上面這個(gè)查詢使用緩存的時(shí)候結(jié)果就是錯(cuò)的。
這點(diǎn)應(yīng)該很容易理解。
在我看來(lái),就以MyBatis目前的緩存方式來(lái)看是無(wú)解的。多表操作根本不能緩存。
如果你讓他們都使用同一個(gè)namespace(通過(guò)<cache-ref>)來(lái)避免臟數(shù)據(jù),那就失去了緩存的意義。
看到這里,實(shí)際上就是說(shuō),二級(jí)緩存不能用。整篇文章介紹這么多也沒(méi)什么用了。
五、挽救二級(jí)緩存?
想更高效率的使用二級(jí)緩存是解決不了了。
但是解決多表操作避免臟數(shù)據(jù)還是有法解決的。解決思路就是通過(guò)攔截器判斷執(zhí)行的sql涉及到那些表(可以用jsqlparser解析),然后把相關(guān)表的緩存自動(dòng)清空。但是這種方式對(duì)緩存的使用效率是很低的。
設(shè)計(jì)這樣一個(gè)插件是相當(dāng)復(fù)雜的,既然我沒(méi)想著去實(shí)現(xiàn),就不廢話了。
最后還是建議,放棄二級(jí)緩存,在業(yè)務(wù)層使用可控制的緩存代替更好。
總結(jié)
以上是生活随笔為你收集整理的Mybatis 为什么不要用二级缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 联想服务器开机自动重启,解决联想电脑开机
- 下一篇: 建设银行网上可以签约吗 建行在网上能不能