mybatis源码解读:executor包(执行器功能)

Bertha 。 2022-10-29 07:41 330阅读 0赞

executor包中的各个子包提供的功能,最终这些功能都由Executor接口及其实现类共同对外提供服务。

Executor接口基于以下方法可以完成增,删,改查以及事务处理等操作。事实上,mybatis中的所有数据库操作是通过调用这些方法实现的。

  1. public interface Executor {
  2. ResultHandler NO_RESULT_HANDLER = null;
  3. // 数据更新操作,其中数据的增加、删除、更新均可由该方法实现
  4. int update(MappedStatement ms, Object parameter) throws SQLException;
  5. // 数据查询操作,返回结果为列表形式
  6. <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
  7. // 数据查询操作,返回结果为列表形式
  8. /**
  9. * 执行查询操作
  10. * @param ms 映射语句对象
  11. * @param parameter 参数对象
  12. * @param rowBounds 翻页限制
  13. * @param resultHandler 结果处理器
  14. * @param <E> 输出结果类型
  15. * @return 查询结果
  16. * @throws SQLException
  17. */
  18. <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
  19. // 数据查询操作,返回结果为游标形式
  20. <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
  21. // 清理缓存
  22. List<BatchResult> flushStatements() throws SQLException;
  23. // 提交事务
  24. void commit(boolean required) throws SQLException;
  25. // 回滚事务
  26. void rollback(boolean required) throws SQLException;
  27. // 创建当前查询的缓存键值
  28. CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
  29. // 本地缓存是否有指定值
  30. boolean isCached(MappedStatement ms, CacheKey key);
  31. // 清理本地缓存
  32. void clearLocalCache();
  33. // 懒加载
  34. void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
  35. // 获取事务
  36. Transaction getTransaction();
  37. // 关闭执行器
  38. void close(boolean forceRollback);
  39. // 判断执行器是否关闭
  40. boolean isClosed();
  41. // 设置执行器包装
  42. void setExecutorWrapper(Executor executor);
  43. }

BaseExecutor是一个抽象类,并用到了模板模式,实现了其子类的一些共有的基础功能,而将与子类直接相关的操作交给子类处理。

  1. public abstract class BaseExecutor implements Executor {
  2. private static final Log log = LogFactory.getLog(BaseExecutor.class);
  3. protected Transaction transaction;
  4. protected Executor wrapper;
  5. protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
  6. // 查询操作的结果缓存
  7. protected PerpetualCache localCache;
  8. // Callable查询的输出参数缓存
  9. protected PerpetualCache localOutputParameterCache;
  10. protected Configuration configuration;
  11. protected int queryStack;
  12. private boolean closed;
  13. /**
  14. * 更新数据库数据,INSERT/UPDATE/DELETE三种操作都会调用该方法
  15. * @param ms 映射语句
  16. * @param parameter 参数对象
  17. * @return 数据库操作结果
  18. * @throws SQLException
  19. */
  20. @Override
  21. public int update(MappedStatement ms, Object parameter) throws SQLException {
  22. ErrorContext.instance().resource(ms.getResource())
  23. .activity("executing an update").object(ms.getId());
  24. if (closed) {
  25. // 执行器已经关闭
  26. throw new ExecutorException("Executor was closed.");
  27. }
  28. // 清理本地缓存
  29. clearLocalCache();
  30. // 返回调用子类进行操作
  31. return doUpdate(ms, parameter);
  32. }
  33. /**
  34. * 执行查询操作
  35. * @param ms 映射语句对象
  36. * @param parameter 参数对象
  37. * @param rowBounds 翻页限制
  38. * @param resultHandler 结果处理器
  39. * @param <E> 输出结果类型
  40. * @return 查询结果
  41. * @throws SQLException
  42. */
  43. @Override
  44. public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
  45. BoundSql boundSql = ms.getBoundSql(parameter);
  46. // 生成缓存的键
  47. CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
  48. return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  49. }
  50. /**
  51. * 查询数据库中的数据
  52. * @param ms 映射语句
  53. * @param parameter 参数对象
  54. * @param rowBounds 翻页限制条件
  55. * @param resultHandler 结果处理器
  56. * @param key 缓存的键
  57. * @param boundSql 查询语句
  58. * @param <E> 结果类型
  59. * @return 结果列表
  60. * @throws SQLException
  61. */
  62. @SuppressWarnings("unchecked")
  63. @Override
  64. public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
  65. ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
  66. if (closed) {
  67. // 执行器已经关闭
  68. throw new ExecutorException("Executor was closed.");
  69. }
  70. if (queryStack == 0 && ms.isFlushCacheRequired()) { // 新的查询栈且要求清除缓存
  71. // 清除一级缓存
  72. clearLocalCache();
  73. }
  74. List<E> list;
  75. try {
  76. queryStack++;
  77. // 尝试从本地缓存获取结果
  78. list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
  79. if (list != null) {
  80. // 本地缓存中有结果,则对于CALLABLE语句还需要绑定到IN/INOUT参数上
  81. handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
  82. } else {
  83. // 本地缓存没有结果,故需要查询数据库
  84. list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
  85. }
  86. } finally {
  87. queryStack--;
  88. }
  89. if (queryStack == 0) {
  90. // 懒加载操作的处理
  91. for (DeferredLoad deferredLoad : deferredLoads) {
  92. deferredLoad.load();
  93. }
  94. deferredLoads.clear();
  95. // 如果本地缓存的作用域为STATEMENT,则立刻清除本地缓存
  96. if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
  97. clearLocalCache();
  98. }
  99. }
  100. return list;
  101. }
  102. /**
  103. * 生成查询的缓存的键
  104. * @param ms 映射语句对象
  105. * @param parameterObject 参数对象
  106. * @param rowBounds 翻页限制
  107. * @param boundSql 解析结束后的SQL语句
  108. * @return 生成的键值
  109. */
  110. @Override
  111. public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
  112. if (closed) {
  113. throw new ExecutorException("Executor was closed.");
  114. }
  115. // 创建CacheKey,并将所有查询参数依次更新写入
  116. CacheKey cacheKey = new CacheKey();
  117. cacheKey.update(ms.getId());
  118. cacheKey.update(rowBounds.getOffset());
  119. cacheKey.update(rowBounds.getLimit());
  120. cacheKey.update(boundSql.getSql());
  121. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  122. TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
  123. for (ParameterMapping parameterMapping : parameterMappings) {
  124. if (parameterMapping.getMode() != ParameterMode.OUT) {
  125. Object value;
  126. String propertyName = parameterMapping.getProperty();
  127. if (boundSql.hasAdditionalParameter(propertyName)) {
  128. value = boundSql.getAdditionalParameter(propertyName);
  129. } else if (parameterObject == null) {
  130. value = null;
  131. } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
  132. value = parameterObject;
  133. } else {
  134. MetaObject metaObject = configuration.newMetaObject(parameterObject);
  135. value = metaObject.getValue(propertyName);
  136. }
  137. cacheKey.update(value);
  138. }
  139. }
  140. if (configuration.getEnvironment() != null) {
  141. cacheKey.update(configuration.getEnvironment().getId());
  142. }
  143. return cacheKey;
  144. }
  145. }

BaseExecutor有四个实现类:

CloseExecutor :仅表明自身已经关闭的执行器,没有其他实际功能

SimpleExecutor : 一个最为简单的执行器

BatchExecutor :支持批量执行功能的执行器

ReuseExecutor : 支持Statement对象复用的执行器。

SimpleExecutor,BatchExecutor,ReuseExecutor 这三个执行器的选择是在mybatis的配置文件中进行的,可选的值由session包中的ExecutorType定义,这三个执行器主要基于StatementHandler完成创建Statement对象,绑定参数等工作。

欢迎关注本人公众号:

20201220181855568.png

发表评论

表情:
评论列表 (有 0 条评论,330人围观)

还没有评论,来说两句吧...

相关阅读