Java編程MyBatis一級緩存和二級緩存的區別,了解一下?

Java編程MyBatis一級緩存和二級緩存的區別,瞭解一下?

鎮樓小姐姐

可獲得兩大新人禮包

36份一線互聯網Java面試電子書

84個Java稀缺面試題視頻


MyBatis自帶的緩存有一級緩存和二級緩存

一級緩存

Mybatis的一級緩存是指Session緩存。一級緩存的作用域默認是一個SqlSession。Mybatis默認開啟一級緩存。

也就是在同一個SqlSession中,執行相同的查詢SQL,第一次會去數據庫進行查詢,並寫到緩存中;

第二次以後是直接去緩存中取。

當執行SQL查詢中間發生了增刪改的操作,MyBatis會把SqlSession的緩存清空。

一級緩存的範圍有SESSION和STATEMENT兩種,默認是SESSION,如果不想使用一級緩存,可以把一級緩存的範圍指定為STATEMENT,這樣每次執行完一個Mapper中的語句後都會將一級緩存清除。

如果需要更改一級緩存的範圍,可以在Mybatis的配置文件中,在下通過localCacheScope指定。

建議不需要修改

需要注意的是

當Mybatis整合Spring後,直接通過Spring注入Mapper的形式,如果不是在同一個事務中每個Mapper的每次查詢操作都對應一個全新的SqlSession實例,這個時候就不會有一級緩存的命中,但是在同一個事務中時共用的是同一個SqlSession。

如有需要可以啟用二級緩存。

二級緩存

Mybatis的二級緩存是指mapper映射文件。二級緩存的作用域是同一個namespace下的mapper映射文件內容,多個SqlSession共享。Mybatis需要手動設置啟動二級緩存。

二級緩存是默認啟用的(要生效需要對每個Mapper進行配置),如想取消,則可以通過Mybatis配置文件中的元素下的子元素來指定cacheEnabled為false。

cacheEnabled默認是啟用的,只有在該值為true的時候,底層使用的Executor才是支持二級緩存的CachingExecutor。具體可參考Mybatis的核心配置類org.apache.ibatis.session.Configuration的newExecutor方法實現。

可以通過源碼看看

... public Executor newExecutor(Transaction transaction) { return this.newExecutor(transaction, this.defaultExecutorType);

} public Executor newExecutor(Transaction transaction, ExecutorType executorType) {

executorType = executorType == null ? this.defaultExecutorType : executorType;

executorType = executorType == null ? ExecutorType.SIMPLE : executorType;

Object 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 (this.cacheEnabled) {//設置為true才執行的

executor = new CachingExecutor((Executor)executor);

}

Executor executor = (Executor)this.interceptorChain.pluginAll(executor); return executor;

}

...

要使用二級緩存除了上面一個配置外,我們還需要在我們每個DAO對應的Mapper.xml文件中定義需要使用的cache

...

...

具體可以看org.apache.ibatis.executor.CachingExecutor類的以下實現

其中使用的cache就是我們在對應的Mapper.xml中定義的cache。

public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {

BoundSql boundSql = ms.getBoundSql(parameterObject);

CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql); return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

} public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {

Cache cache = ms.getCache(); if (cache != null) {//第一個條件 定義需要使用的cache

this.flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) {//第二個條件 需要當前的查詢語句是配置了使用cache的,即下面源碼的useCache()是返回true的 默認是true

this.ensureNoOutParams(ms, parameterObject, boundSql);

List list = (List)this.tcm.getObject(cache, key); if (list == null) {

list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); this.tcm.putObject(cache, key, list);

} return list;

}

} return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

}

還有一個條件就是需要當前的查詢語句是配置了使用cache的,即上面源碼的useCache()是返回true的,默認情況下所有select語句的useCache都是true,如果我們在啟用了二級緩存後,有某個查詢語句是我們不想緩存的,則可以通過指定其useCache為false來達到對應的效果。

如果我們不想該語句緩存,可使用useCache=”false