十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本篇文章給大家分享的是有關(guān)Mybatis中緩存的方式有哪些,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
通過查看源碼可知,一級緩存是綁定sqSsession中的,所以每次查詢sqlSession不同就失效,相同的sqlSession可以使用一級緩存。
mybatis默認sqlsession:org.apache.ibatis.session.defaults.DefaultSqlSession
構(gòu)造方法中傳入executor(查詢執(zhí)行對象)
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; }
executor中攜帶一級緩存成員:
protected BaseExecutor(Configuration configuration, Transaction transaction) { this.transaction = transaction; this.deferredLoads = new ConcurrentLinkedQueue<>(); this.localCache = new PerpetualCache("LocalCache"); //默認一級緩存 this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache"); this.closed = false; this.configuration = configuration; this.wrapper = this; }
org.apache.ibatis.executor.BaseExecutor.query()
publicList query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); List list; try { queryStack++; //localCache 一級緩存 list = resultHandler == null ? (List ) localCache.getObject(key) : null; //先從一級緩存中獲取,key是通過sql語句生成 if (list != null) { handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { // 如果緩存中沒有 才從數(shù)據(jù)庫查詢 list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { queryStack--; } return list; } //從數(shù)據(jù)庫讀取數(shù)據(jù) private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List list; localCache.putObject(key, EXECUTION_PLACEHOLDER); try { list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { localCache.removeObject(key);//將一級緩存清除 } localCache.putObject(key, list);//返回查詢結(jié)果之前,先放入一級緩存 刷新 if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; }
二級緩存mapper中的,默認是開啟的,但需要在映射文件mapper.xml中添加
配置false可以關(guān)閉二級緩存
org.apache.ibatis.builder.xml.XMLMapperBuilder
private void configurationElement(XNode context) { try { //... cacheElement(context.evalNode("cache")); //解析cache標簽 } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } } private void cacheElement(XNode context) { if (context != null) { // if hava cache tag 如果有cache標簽才執(zhí)行下面的邏輯 String type = context.getStringAttribute("type", "PERPETUAL"); Class extends Cache> typeClass = typeAliasRegistry.resolveAlias(type); String eviction = context.getStringAttribute("eviction", "LRU"); Class extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction); Long flushInterval = context.getLongAttribute("flushInterval"); Integer size = context.getIntAttribute("size"); boolean readWrite = !context.getBooleanAttribute("readOnly", false); boolean blocking = context.getBooleanAttribute("blocking", false); Properties props = context.getChildrenAsProperties(); builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);//建立二級緩存 } }
org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache():
public Cache useNewCache(Class extends Cache> typeClass, Class extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) { Cache cache = new CacheBuilder(currentNamespace) .implementation(valueOrDefault(typeClass, PerpetualCache.class)) .addDecorator(valueOrDefault(evictionClass, LruCache.class)) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .blocking(blocking) .properties(props) .build(); configuration.addCache(cache);//二級緩存賦值,如果cache標簽為空,不會執(zhí)行此方法,currentCache為空 currentCache = cache; return cache; }
在映射文件mapper中如果沒有cache標簽,不會執(zhí)行上面的useNewCache方法,cache為null,就不會使用二級緩存(相當(dāng)于失效)。
org.apache.ibatis.executor.CachingExecutor :
@Override publicList query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); if (cache != null) {//如果二級緩存對象不為空 嘗試在二級緩存中獲?。]有cache標簽此對象就是空) flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, boundSql); @SuppressWarnings("unchecked") List list = (List ) tcm.getObject(cache, key); //從二級緩存中獲取數(shù)據(jù) if (list == null) { list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //如果為空,使用delegate查詢(BaseExecutor) tcm.putObject(cache, key, list); // 查詢結(jié)果保存到二級緩存 } return list; } } return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }
二級緩存和一級緩存不用想,數(shù)據(jù)庫的數(shù)據(jù)被修改是要清空緩存的,不然數(shù)據(jù)有誤,至于怎么清空,是另一套邏輯了,mapper中的cache標簽可以配置一些參數(shù),比如緩存定期清空。
mybatis默認是先查詢二級緩存,沒有,再查看一級緩存,都為空,最后查詢數(shù)據(jù)庫
以上就是Mybatis中緩存的方式有哪些,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。