MyBatis SQL执行
SQL 语句的执行涉及多个组件 ,其中比较重要的是 Executor、StatementHandler、ParameterHandler 和 ResultSetHandler 。
- Executor 主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,它会将数据库相关操作委托给StatementHandler完成。
- StatementHandler 首先通过 ParameterHandler 完成 SQL 语句的实参绑定,然后通过
java.sql.Statement
对象执行 SQL 语句并得到结果集,最后通过 ResultSetHandler 完成结果集的映射,得到结果对象并返回。
SqlSession
对象表示MyBaits框架与数据库建立的会话,我们可以通过SqlSession
实例完成对数据库的增删改查操作。SqlSession
是一个接口,它的默认实现为DefaultSqlSession
。
DefaultSqlSession
下面以selectOne为例
// DefaultSqlSession.java
public class DefaultSqlSession implements SqlSession {
private final Configuration configuration;
private final Executor executor;
private final boolean autoCommit;
private boolean dirty;
private List<Cursor<?>> cursorList;
@Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 根据 statement 获取对应的 MappedStatement
// statement = Mapper类路径.方法名
// 如com.example.demo.UserMapper.getUserByUserName
MappedStatement ms = configuration.getMappedStatement(statement);
// 这里的 executor 使用的是 CachingExecutor
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
CachingExecutor
// CachingExecutor.java
public class CachingExecutor implements Executor {
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
// 创建 CacheKey 对象
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
// 查询
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
// 这里判断是否需要清空缓存
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
// 这里是存储过程相关的
ensureNoOutParams(ms, parameterObject, boundSql);
// 从二级缓存中获取结果
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
// 如果不存在,则从数据库中查询
// 这里的 delegate 为 SimpleExecutor,SimpleExecutor继承了BaseExecutor
// 这里的 query 方法是 BaseExecutor 类中的
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
// 缓存结果到二级缓存中
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
// 不使用缓存,则从数据库中查询
// 这里的 delegate 为 SimpleExecutor,SimpleExecutor继承了BaseExecutor
// 这里的 query 方法是 BaseExecutor 类中的
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
}
BaseExecutor
// BaseExecutor.java
public abstract class BaseExecutor implements Executor {
@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) {
throw new ExecutorException("Executor was closed.");
}
// 清空本地缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
// 用来保存结果列表
List<E> list;
try {
queryStack++;
// 从一级缓存中查询结果
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
// 存储过程相关
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
// 获取不到则从数据库中查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 在缓存中添加占位对象。这里的占位符和延迟加载有关系。
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 执行读操作
// 这里的 doQuery 由子类SimpleExecutor实现
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 从缓存中移除占位对象
localCache.removeObject(key);
}
// 将结果添加到缓存中
localCache.putObject(key, list);
// 存储过程相关
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
// 返回查询结果
return list;
}
}
SimpleExecutor
// SimpleExecutor.java
public class SimpleExecutor extends BaseExecutor {
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
// 获取 Configuration
Configuration configuration = ms.getConfiguration();
// 创建 StatementHandler 对象
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 获取 Statement 对象
stmt = prepareStatement(handler, ms.getStatementLog());
// 执行查询操作
// 这里的 handler 为 RoutingStatementHandler
return handler.<E>query(stmt, resultHandler);
} finally {
// 关闭 StatementHandler 对象
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 获得 Connection 对象
Connection connection = getConnection(statementLog);
// 创建 Statement 或 PrepareStatement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
// 设置 SQL 上的参数,例如 PrepareStatement 对象上的占位符设置上用户传递过来的值
// 这里的 handler 为 RoutingStatementHandler
handler.parameterize(stmt);
return stmt;
}
}
RoutingStatementHandler
// RoutingStatementHandler.java
public class RoutingStatementHandler implements StatementHandler {
// 完成SQL语句的实参绑定
@Override
public void parameterize(Statement statement) throws SQLException {
// 这里的 delegate 为 PreparedStatementHandler
delegate.parameterize(statement);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
// 这里的 delegate 为 PreparedStatementHandler
return delegate.<E>query(statement, resultHandler);
}
}
PreparedStatementHandler
// PreparedStatementHandler.java
public class PreparedStatementHandler extends BaseStatementHandler {
// 完成SQL语句的实参绑定
@Override
public void parameterize(Statement statement) throws SQLException {
// 这里的 parameterHandler 为
parameterHandler.setParameters((PreparedStatement) statement);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
// 这里的 resultSetHandler 为 DefaultResultSetHandler
// handleResultSets方法的功能是将查询结果封装成用户设置的返回类型
return resultSetHandler.<E> handleResultSets(ps);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接