Mybatis源码分析(5) -- StatementHandler分析
这一篇我们要分析一下StamentHandler的功能,在前面分析Executor的时候就提到过StatementHandler,Executor并没有真正的去执行数据库操作,而是交由StatementHanlder来处理的。
下面我们先看看StamentHandler接口提供的方法:
public interface StatementHandler {
//从Connection中获取Stament对象
Statement prepare(Connection connection) throws SQLException;
//设置预处理参数
void parameterize(Statement statement) throws SQLException;
//调用批量操作
void batch(Statement statement) throws SQLException;
//更新操作
int update(Statement statement) throws SQLException;
//查询操作
<E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;
//获取执行SQL语句的封装类BoundSql
BoundSql getBoundSql();
//参数处理器
ParameterHandler getParameterHandler();
}
从StatementHandler接口功能来分析,StatementHandler主要提供了以下几个功能:
- 获取Statement实例,获取SQL封装
- 查询、修改数据库操作
- 处理预处理参数
StatementHandler接口的实现图是这样的:
StatementHandler
|-------BaseStatementHandler(基础抽象语句处理器)
|-----------SimpleStatementHandler(简单SQL语句处理器)
|-----------PreparedStatementHandler(参数化SQL预定义处理器)
|-----------CallableStatementHandler(存储过程处理器)
|-------RoutingStatementHandler(路由语句处理器)
下面我们分析一下各个实现类,对于CallableStatementHandler(存储过程处理器)这个就不分析了,平时用的也不多,大家可以自己看看。
BaseStatementHandler 基础抽象语句处理器
BaseStatementHandler是对StatementHandler最基础的实现,直接分析整个类。
public abstract class BaseStatementHandler implements StatementHandler {
//配置对象,用于获取配置信息
protected final Configuration configuration;
//用于结果集对象的实例化创建
protected final ObjectFactory objectFactory;
//用于结果集字段类型转换
protected final TypeHandlerRegistry typeHandlerRegistry;
//结果集处理器,用于处理结果集
protected final ResultSetHandler resultSetHandler;
//参数处理器,用于处理预处理参数
protected final ParameterHandler parameterHandler;
//执行器
protected final Executor executor;
//SQL元数据的封装
protected final MappedStatement mappedStatement;
//用于处理结果集的行定位
protected final RowBounds rowBounds;
//封装了执行的SQL
protected BoundSql boundSql;
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
//如果没有传入boundSql,则内部生成
if (boundSql == null) {
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
public Statement prepare(Connection connection) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//Statement的创建由抽象方法去实现
statement = instantiateStatement(connection);
//设置语句查询超时
setStatementTimeout(statement);
//设置获取值
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
//创建Statment,由子类去实现
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
protected void setStatementTimeout(Statement stmt) throws SQLException {
Integer timeout = mappedStatement.getTimeout();
Integer defaultTimeout = configuration.getDefaultStatementTimeout();
if (timeout != null) {
stmt.setQueryTimeout(timeout);
} else if (defaultTimeout != null) {
stmt.setQueryTimeout(defaultTimeout);
}
}
protected void setFetchSize(Statement stmt) throws SQLException {
Integer fetchSize = mappedStatement.getFetchSize();
if (fetchSize != null) {
stmt.setFetchSize(fetchSize);
}
}
// 关闭Statement
protected void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
//ignore
}
}
// 使用键生成器生成key
protected void generateKeys(Object parameter) {
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
ErrorContext.instance().store();
keyGenerator.processBefore(executor, mappedStatement, null, parameter);
ErrorContext.instance().recall();
}
}
BaseStatementHandler的实现很简单,为子类提供了共用的属性以及一个instantiateStatement(Connection connection)抽象方法,子类由这个抽象方法来创建具体的Statement实例,Statement、PreparedStatement、CallableStatement分别由子类提供。
SimpleStatementHandler 简单SQL语句处理器
public class SimpleStatementHandler extends BaseStatementHandler {
public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
public int update(Statement statement) throws SQLException {
// 获取执行SQL
String sql = boundSql.getSql();
// 获取参数
Object parameterObject = boundSql.getParameterObject();
// 键生成器
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
//执行SQL语句,并获取影响的行数
if (keyGenerator instanceof Jdbc3KeyGenerator) {
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
statement.execute(sql);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else {
statement.execute(sql);
rows = statement.getUpdateCount();
}
//返回语句执行影响的行数
return rows;
}
// 批量操作
public void batch(Statement statement) throws SQLException {
String sql = boundSql.getSql();
statement.addBatch(sql);
}
// 查询功能
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
//真实的调用JDBC操作数据库,将结果集交给ResultSetHandler去处理
statement.execute(sql);
return resultSetHandler.<E>handleResultSets(statement);
}
//创建Statment实例
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() != null) {
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.createStatement();
}
}
public void parameterize(Statement statement) throws SQLException {
//Statement执行不需要设置预定义参数
}
}
PreparedStatementHandler 参数化SQL预定义处理器
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//执行SQL语句,获取影响的行数
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
//返回执行影响的行数
return rows;
}
// 批量操作
public void batch(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.addBatch();
}
// 查询操作
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//真实的调用JDBC操作数据库,将结果集交给ResultSetHandler去处理
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
//创建PreparedStament实例
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.prepareStatement(sql);
}
}
public void parameterize(Statement statement) throws SQLException {
//设置预定义参数,由参数处理器来设置
parameterHandler.setParameters((PreparedStatement) statement);
}
}
RoutingStatementHandler 路由语句处理器
RoutingStatementHandler是根据不同的statementType来选择创建不同的实例。这里就是用了简单工厂模式,根据不同的StatementType类型来创建相应的实例对象,然后具体的操作由这个delegate来处理。
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
public Statement prepare(Connection connection) throws SQLException {
return delegate.prepare(connection);
}
public void parameterize(Statement statement) throws SQLException {
delegate.parameterize(statement);
}
public void batch(Statement statement) throws SQLException {
delegate.batch(statement);
}
public int update(Statement statement) throws SQLException {
return delegate.update(statement);
}
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.<E>query(statement, resultHandler);
}
public BoundSql getBoundSql() {
return delegate.getBoundSql();
}
public ParameterHandler getParameterHandler() {
return delegate.getParameterHandler();
}
}
StatementHandler的源码我们都已经分析的差不多了,前面在分析Executor时就知道实际的数据库操作是委派给StatementHandler来处理的。那么,StatementHandler又是怎么创建的呢?StatementHandler是通过如下代码创建的:
StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
StatementHandler的创建在Configuration中,下面我们看看这个方法:
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//创建RoutingStatementHandler,具体的子类需要根据StatementType去选择
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
//如果设置了Interceptor,RoutingStatementHandler对象会被拦截器代理,关于拦截器是如何代理的,后面再说
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
//返回被代理的StatementHandler对象
return statementHandler;
}
StatementHandler很简单,就分析到这里了。StatementHandler执行SQL后结果集会交由ResultSetHandler去处理,下一篇中我们再看看结果集是怎么处理的。