標簽(空格分隔): mybatis
緩存概述
- mybatis存在一級緩存和二級緩存
- 一級緩存在BaseExecutor中實現,二級緩存在CachingExecutor中實現。
- mybatis緩存采用了裝飾器和委托模式。(LoggingCache、SynchronizedCache是其裝飾類)
- 一級緩存和二級緩存都存放在PerpetualCache對象中,PerpetualCache持有一個Map<Object, Object> Cache屬性
Key為CacheKey,Value為sql執行后的結果集。CacheKey 根據namespace、offset、limit、sql輸個屬性生成。 - 二級緩存支持其他緩存介質接入。
立即開始
***Mapper.xml 配置中加入,這里啟用了二級緩存。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
- evication 表示緩存采用的淘汰策略,flushInterval表示緩存的刷新時間,size表示緩存數量到達多大時刷新,readOnly則表示緩存是否只讀。
- 在mybatis初始化時會把mapper.xml解析成StatementMapper對象,StatementMapper維護一個cache對象,二級緩存是和StatementMapper綁定在一起的。
代碼
- 從上面的包名和類名我們可以看出,mybatis的緩存采用了裝飾器模式。委托模式在CachingExecutor類中能看出來。
一級緩存
-
一級緩存在BaseExecutor類中實現,在152行中,如果返回結果不為空,並且能在localCache中get到數據,mybatis就不會再去查詢數據庫。 其中的localCache是一個PerpetualCache對象。
-
由於BaseExecutor是BatchExecutor、ReuseExecutor、SimpleExecutor的父類。在執行查詢(query)時,mybatis都會判斷localCache是否存在緩存,如果存在就返回緩存中的值。言外之意就是一級緩存是默認開啟的。
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
} -
CachingExecutor 實現了二級緩存,interceptorChain在這里實現了Executor級別的攔截,返回了一個被代理得執行器對象。CachingExecutor持有了一個BaseExecutor的委托對象,這里就是委托模式得運用。