🚀 作者主頁: 有來技術
🔥 開源項目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot
🌺 倉庫主頁: Gitee 💫 Github 💫 GitCode
💖 歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請糾正!
目錄
- 前言
- Executor 的作用與分類
- Executor 的源碼解析
- SimpleExecutor
- ReuseExecutor
- BatchExecutor
- CachingExecutor 的作用
- 結語
- 開源項目
前言
MyBatis 作為一個強大的持久層框架,其靈活的映射機制和高效的數據庫操作在Java開發中得到了廣泛應用。其中,MyBatis 的四大核心組件之一 Executor,負責執行SQL語句、管理緩存以及處理查詢結果。在本文中,將深度解析 MyBatis Executor 的內部工作原理,并對其一個關鍵實現組件——CachingExecutor 進行簡要介紹。
Executor 的作用與分類
Executor是MyBatis的核心組件之一,主要負責以下職責:
-
執行 SQL 語句: Executor將用戶傳入的SQL語句交由StatementHandler處理,并執行最終的SQL操作。
-
緩存管理: 管理MyBatis的一級緩存(本地緩存)和二級緩存(全局緩存)。
-
結果集映射: 將數據庫返回的結果集映射為Java對象。
根據具體實現方式,Executor分為三種主要類型:
-
SimpleExecutor: 每執行一次update或select,就開啟一個Statement對象,用完立即關閉。
-
ReuseExecutor: 執行update或select,以SQL語句作為key查找Statement對象,存在就使用,不存在就創建,用完不關閉Statement對象,而是放置于Map內,供下一次使用。
-
BatchExecutor: 批量執行Statement,沒有二級緩存功能。
Executor 的源碼解析
SimpleExecutor
SimpleExecutor是MyBatis默認的Executor實現,其關鍵源碼如下:
public class SimpleExecutor extends BaseExecutor {@Overridepublic int doUpdate(MappedStatement ms, Object parameter) throws SQLException {Statement stmt = null;try {Configuration configuration = ms.getConfiguration();StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);stmt = prepareStatement(handler, ms.getStatementLog());return handler.update(stmt);} finally {closeStatement(stmt);}}@Override@SuppressWarnings("unchecked")public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = null;try {Configuration configuration = ms.getConfiguration();StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);stmt = prepareStatement(handler, ms.getStatementLog());return handler.<E>query(stmt, resultHandler);} finally {closeStatement(stmt);}}// ... 其他方法 ...
}
ReuseExecutor
ReuseExecutor在執行update或select時,通過SQL語句作為key緩存Statement對象,下次執行相同的SQL語句時直接從緩存中獲取:
public class ReuseExecutor extends BaseExecutor {private final Map<String, Statement> statementMap = new HashMap<>();@Overridepublic int doUpdate(MappedStatement ms, Object parameter) throws SQLException {Statement stmt = null;try {Configuration configuration = ms.getConfiguration();StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);stmt = prepareStatement(handler, ms.getStatementLog());return handler.update(stmt);} finally {closeStatement(stmt);}}@Override@SuppressWarnings("unchecked")public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = statementMap.get(ms.getKey());try {if (stmt == null) {Configuration configuration = ms.getConfiguration();StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);stmt = prepareStatement(handler, ms.getStatementLog());List<E> result = handler.<E>query(stmt, resultHandler);statementMap.put(ms.getKey(), stmt);return result;} else {return handleQueryResult(ms, parameter, rowBounds, resultHandler, stmt);}} finally {// ...}}// ... 其他方法 ...
}
BatchExecutor
BatchExecutor 專門用于批量執行 Statement,沒有二級緩存功能。適用于需要一次性執行多個 SQL 語句的場景。
public class BatchExecutor extends BaseExecutor {@Overridepublic int doUpdate(MappedStatement ms, Object parameter) throws SQLException {// 執行更新操作return delegate.update(ms, parameter);}@Override@SuppressWarnings("unchecked")public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {// 執行查詢操作return delegate.<E>query(ms, parameter, rowBounds, resultHandler, ms.getKey(), boundSql);}// ... 其他方法 ...
}
CachingExecutor 的作用
CachingExecutor 通過緩存機制在一級緩存和二級緩存中提高查詢性能。其工作原理涉及一級緩存和二級緩存的處理:
- 一級緩存處理: 在執行查詢操作時,``CachingExecutor 首先通過 delegate 執行SQL語句,然后將查詢結果存儲到一級緩存中,以提高后續相同查詢的性能。
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {// 從緩存中獲取結果List<E> list = delegate.query(ms, parameter, rowBounds, resultHandler, key, boundSql);// 將結果添加到緩存tcm.putObject(key, list);return list;
}
- 二級緩存處理: 在執行更新操作時,
CachingExecutor
會清空一級緩存,然后通過 delegate 執行實際的更新操作。在事務提交時,將一級緩存中的數據寫入二級緩存中,以便多個SqlSession
共享相同的數據。
public int update(MappedStatement ms, Object parameter) throws SQLException {// 清空一級緩存flushCacheIfRequired(ms);// 執行更新操作int count = delegate.update(ms, parameter);// 提交事務時,將緩存數據寫入二級緩存tcm.commit();return count;
}
結語
本文深入解析 MyBatis 四大核心組件之一的 Executor,著重介紹 SimpleExecutor、ReuseExecutor、BatchExecuto r的源碼實現,同時補充CacheExecutor的作用與示例。通過源碼解析和示例,全面理解MyBatis持久層框架的關鍵組件。
開源項目
- SpringCloud + Vue3 微服務商城
Github | Gitee | |
---|---|---|
后端 | youlai-mall 🍃 | youlai-mall 🍃 |
前端 | mall-admin🌺 | mall-admin 🌺 |
移動端 | mall-app 🍌 | mall-app 🍌 |
- SpringBoot 3+ Vue3 單體權限管理系統
Github | Gitee | |
---|---|---|
后端 | youlai-boot 🍃 | youlai-boot 🍃 |
前端 | vue3-element-admin 🌺 | vue3-element-admin 🌺 |