Executor
该接口中定义了操作数据库的各种方法,是mybatis的核心接口之一,是SqlSession接口的基础,其定义如下:
public interface Executor {
ResultHandler NO_RESULT_HANDLER = null;
//执行增删改操作
int update(MappedStatement ms, Object parameter) throws SQLException;
//执行查询操作
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
<E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
//批量执行sql
List<BatchResult> flushStatements() throws SQLException;
//提交事务
void commit(boolean required) throws SQLException;
//回滚事务
void rollback(boolean required) throws SQLException;
//创建缓存的key
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();
//关闭执行器
void close(boolean forceRollback);
//是否关闭
boolean isClosed();
//设置委派的执行器对象
void setExecutorWrapper(Executor executor);
}
类图
Executor接口及其实现使用了模板设计模式,抽象类BaseExecutor实现了Executor接口中的大部分方法,BatchExecutor、ReuseExecutor和SimpleExecutor只需要根据自身的需求实现少量的方法即可,利用面向对象多态的特性,提高了系统的灵活性和扩展性。
BaseExecutor
抽象类BaseExecutor是Executor接口的基本实现,他实现了大部分接口,提供了缓存和事务相关的实现,使得其子类只需要实现和数据库相关的功能即可。
属性
private static final Log log = LogFactory.getLog(BaseExecutor.class);
//事务对象
protected Transaction transaction;
//持有的执行器对象
protected Executor wrapper;
//延迟加载队列
protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
//一级缓存
protected PerpetualCache localCache;
//保存输出参数的缓存
protected PerpetualCache localOutputParameterCache;
//全局配置对象
protected Configuration configuration;
//嵌套查询层数
protected int queryStack;
//Executor是否已经被关闭的标志位
private boolean closed;
构造函数
protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<>();
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}
缓存相关
这里的缓存就是常说的一级缓存,缓存的优势不用多说,这里需要强调的是mybatis一级缓存的作用域与SqlSession对象相同,而SqlSession对象中又持有Executor对象,所以mybatis一级缓存的作用域也与Executor对象相同。mybatis的一级缓存功能模式是开启的。
createCacheKey
创建缓存的key,使用缓存模块的CacheKey对象来构建缓存的key。从下面的代码可以看出,缓存的key关注以下部分:
- MappedStatement的ID
- rowBounds对象的偏移量属性
- rowBounds对象的limit属性
- sql语句(带?占位符)
- 用户传入的实参
- Environment的ID属性
也就是说,如果上述6个部分都相同的话,则mybatis认为这是同一个对象
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed