executor包執(zhí)行器功能
Executor接口基于以下方法可以完成增,刪,改查以及事務處理等操作。事實上,mybatis中的所有數(shù)據(jù)庫操作是通過調(diào)用這些方法實現(xiàn)的。
public interface Executor {
?
? ResultHandler NO_RESULT_HANDLER = null;
?
? // 數(shù)據(jù)更新操作,其中數(shù)據(jù)的增加、刪除、更新均可由該方法實現(xiàn)
? int update(MappedStatement ms, Object parameter) throws SQLException;
? // 數(shù)據(jù)查詢操作,返回結(jié)果為列表形式
? <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
? // 數(shù)據(jù)查詢操作,返回結(jié)果為列表形式
? /**
? ?* 執(zhí)行查詢操作
? ?* @param ms 映射語句對象
? ?* @param parameter 參數(shù)對象
? ?* @param rowBounds 翻頁限制
? ?* @param resultHandler 結(jié)果處理器
? ?* @param <E> 輸出結(jié)果類型
? ?* @return 查詢結(jié)果
? ?* @throws SQLException
? ?*/
? <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
? // 數(shù)據(jù)查詢操作,返回結(jié)果為游標形式
? <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
? // 清理緩存
? List<BatchResult> flushStatements() throws SQLException;
? // 提交事務
? void commit(boolean required) throws SQLException;
? // 回滾事務
? void rollback(boolean required) throws SQLException;
? // 創(chuàng)建當前查詢的緩存鍵值
? CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
? // 本地緩存是否有指定值
? boolean isCached(MappedStatement ms, CacheKey key);
? // 清理本地緩存
? void clearLocalCache();
? // 懶加載
? void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
? // 獲取事務
? Transaction getTransaction();
? // 關(guān)閉執(zhí)行器
? void close(boolean forceRollback);
? // 判斷執(zhí)行器是否關(guān)閉
? boolean isClosed();
? // 設(shè)置執(zhí)行器包裝
? void setExecutorWrapper(Executor executor);
?
}BaseExecutor是一個抽象類,并用到了模板模式,實現(xiàn)了其子類的一些共有的基礎(chǔ)功能,而將與子類直接相關(guān)的操作交給子類處理。
public abstract class BaseExecutor implements Executor {
?
? private static final Log log = LogFactory.getLog(BaseExecutor.class);
?
? protected Transaction transaction;
? protected Executor wrapper;
?
? protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
? // 查詢操作的結(jié)果緩存
? protected PerpetualCache localCache;
? // Callable查詢的輸出參數(shù)緩存
? protected PerpetualCache localOutputParameterCache;
? protected Configuration configuration;
?
? protected int queryStack;
? private boolean closed;
?
?
?
?
? /**
? ?* 更新數(shù)據(jù)庫數(shù)據(jù),INSERT/UPDATE/DELETE三種操作都會調(diào)用該方法
? ?* @param ms 映射語句
? ?* @param parameter 參數(shù)對象
? ?* @return 數(shù)據(jù)庫操作結(jié)果
? ?* @throws SQLException
? ?*/
? @Override
? public int update(MappedStatement ms, Object parameter) throws SQLException {
? ? ErrorContext.instance().resource(ms.getResource())
? ? ? ? ? ? .activity("executing an update").object(ms.getId());
? ? if (closed) {
? ? ? // 執(zhí)行器已經(jīng)關(guān)閉
? ? ? throw new ExecutorException("Executor was closed.");
? ? }
? ? // 清理本地緩存
? ? clearLocalCache();
? ? // 返回調(diào)用子類進行操作
? ? return doUpdate(ms, parameter);
? }
?
??
?
? /**
? ?* 執(zhí)行查詢操作
? ?* @param ms 映射語句對象
? ?* @param parameter 參數(shù)對象
? ?* @param rowBounds 翻頁限制
? ?* @param resultHandler 結(jié)果處理器
? ?* @param <E> 輸出結(jié)果類型
? ?* @return 查詢結(jié)果
? ?* @throws SQLException
? ?*/
? @Override
? public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
? ? BoundSql boundSql = ms.getBoundSql(parameter);
? ? // 生成緩存的鍵
? ? CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
? ? return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
? }
?
? /**
? ?* 查詢數(shù)據(jù)庫中的數(shù)據(jù)
? ?* @param ms 映射語句
? ?* @param parameter 參數(shù)對象
? ?* @param rowBounds 翻頁限制條件
? ?* @param resultHandler 結(jié)果處理器
? ?* @param key 緩存的鍵
? ?* @param boundSql 查詢語句
? ?* @param <E> 結(jié)果類型
? ?* @return 結(jié)果列表
? ?* @throws SQLException
? ?*/
? @SuppressWarnings("unchecked")
? @Override
? public <E> List<E> 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());
? ? if (closed) {
? ? ? // 執(zhí)行器已經(jīng)關(guān)閉
? ? ? throw new ExecutorException("Executor was closed.");
? ? }
? ? if (queryStack == 0 && ms.isFlushCacheRequired()) { // 新的查詢棧且要求清除緩存
? ? ? // 清除一級緩存
? ? ? clearLocalCache();
? ? }
? ? List<E> list;
? ? try {
? ? ? queryStack++;
? ? ? // 嘗試從本地緩存獲取結(jié)果
? ? ? list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
? ? ? if (list != null) {
? ? ? ? // 本地緩存中有結(jié)果,則對于CALLABLE語句還需要綁定到IN/INOUT參數(shù)上
? ? ? ? handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
? ? ? } else {
? ? ? ? // 本地緩存沒有結(jié)果,故需要查詢數(shù)據(jù)庫
? ? ? ? list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
? ? ? }
? ? } finally {
? ? ? queryStack--;
? ? }
? ? if (queryStack == 0) {
? ? ? // 懶加載操作的處理
? ? ? for (DeferredLoad deferredLoad : deferredLoads) {
? ? ? ? deferredLoad.load();
? ? ? }
? ? ? deferredLoads.clear();
? ? ? // 如果本地緩存的作用域為STATEMENT,則立刻清除本地緩存
? ? ? if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
? ? ? ? clearLocalCache();
? ? ? }
? ? }
? ? return list;
? }
?
??
?
? /**
? ?* 生成查詢的緩存的鍵
? ?* @param ms 映射語句對象
? ?* @param parameterObject 參數(shù)對象
? ?* @param rowBounds 翻頁限制
? ?* @param boundSql 解析結(jié)束后的SQL語句
? ?* @return 生成的鍵值
? ?*/
? @Override
? public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
? ? if (closed) {
? ? ? throw new ExecutorException("Executor was closed.");
? ? }
? ? // 創(chuàng)建CacheKey,并將所有查詢參數(shù)依次更新寫入
? ? CacheKey cacheKey = new CacheKey();
? ? cacheKey.update(ms.getId());
? ? cacheKey.update(rowBounds.getOffset());
? ? cacheKey.update(rowBounds.getLimit());
? ? cacheKey.update(boundSql.getSql());
? ? List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
? ? TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
? ? for (ParameterMapping parameterMapping : parameterMappings) {
? ? ? if (parameterMapping.getMode() != ParameterMode.OUT) {
? ? ? ? Object value;
? ? ? ? String propertyName = parameterMapping.getProperty();
? ? ? ? if (boundSql.hasAdditionalParameter(propertyName)) {
? ? ? ? ? value = boundSql.getAdditionalParameter(propertyName);
? ? ? ? } else if (parameterObject == null) {
? ? ? ? ? value = null;
? ? ? ? } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
? ? ? ? ? value = parameterObject;
? ? ? ? } else {
? ? ? ? ? MetaObject metaObject = configuration.newMetaObject(parameterObject);
? ? ? ? ? value = metaObject.getValue(propertyName);
? ? ? ? }
? ? ? ? cacheKey.update(value);
? ? ? }
? ? }
? ? if (configuration.getEnvironment() != null) {
? ? ? cacheKey.update(configuration.getEnvironment().getId());
? ? }
? ? return cacheKey;
? }
}BaseExecutor有四個實現(xiàn)類:
CloseExecutor:僅表明自身已經(jīng)關(guān)閉的執(zhí)行器,沒有其他實際功能SimpleExecutor: 一個最為簡單的執(zhí)行器BatchExecutor:支持批量執(zhí)行功能的執(zhí)行器ReuseExecutor: 支持Statement對象復用的執(zhí)行器。
SimpleExecutor,BatchExecutor,ReuseExecutor 這三個執(zhí)行器的選擇是在mybatis的配置文件中進行的,可選的值由session包中的ExecutorType定義,這三個執(zhí)行器主要基于StatementHandler完成創(chuàng)建Statement對象,綁定參數(shù)等工作。
到此這篇關(guān)于executor包執(zhí)行器功能的文章就介紹到這了,更多相關(guān)executor包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
lazy?init控制加載在Spring中如何實現(xiàn)源碼分析
這篇文章主要為大家介紹了lazy?init控制加載在Spring中如何實現(xiàn)源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09
springboot實現(xiàn)指定mybatis中mapper文件掃描路徑
這篇文章主要介紹了springboot實現(xiàn)指定mybatis中mapper文件掃描路徑方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Java中比較器Comparator和Comparable的區(qū)別
這篇文章主要介紹了Java中比較器Comparator和Comparable的區(qū)別,我們在使用?Collections.sort()對鏈表進行排序時,常常需要根據(jù)不同情況自定義排序規(guī)則,今天我們來看看比較器之間的區(qū)別,需要的朋友可以參考下2023-08-08
java中利用反射調(diào)用另一類的private方法的簡單實例
下面小編就為大家?guī)硪黄猨ava中利用反射調(diào)用另一類的private方法的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06
解決spring中redistemplate不能用通配符keys查出相應Key的問題
這篇文章主要介紹了解決spring中redistemplate不能用通配符keys查出相應Key的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

