上篇讲完了Executor接口及其实现类,接下来分析StatementHandler,这是Executor用来处理Statement的。
首先是StatementHandler的接口
public interface StatementHandler {
//从连接中获取一个Statement
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
//占位符处理,绑定statement执行时需要的实参
void parameterize(Statement statement)
throws SQLException;
//批量执行sql语句
void batch(Statement statement)
throws SQLException;
//执行update/insert/delete语句
int update(Statement statement)
throws SQLException;
//执行select语句
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
<E> Cursor<E> queryCursor(Statement statement)
throws SQLException;
//获取sql语句
BoundSql getBoundSql();
//获取封装的参数处理器
ParameterHandler getParameterHandler();
}
RoutingStatementHandler 负责将不同的Statement类型路由到三个不同的实现类上。
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;//底层封装的真正的StatementHandler对象
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//RoutingStatementHandler最主要的功能就是根据mappedStatment的配置,生成一个对应的StatementHandler对象并赋值给delegate
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());
}
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
return delegate.prepare(connection, transactionTimeout);
}
@Override
public void parameterize(Statement statement) throws SQLException {
delegate.parameterize(statement);
}
@Override
public void batch(Statement statement) throws SQLException {
delegate.batch(statement);
}
@Override
public int update(Statement statement) throws SQLException {
return delegate.update(statement);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.<E>query(statement, resultHandler);
}
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
return delegate.queryCursor(statement);
}
@Override
public BoundSql getBoundSql() {
return delegate.getBoundSql();
}
@Override
public ParameterHandler getParameterHandler() {
return delegate.getParameterHandler();
}
}
BaseStatementHandler 实现了StatementHandler的基类,提供了骨架(模版模式)
public abstract class BaseStatementHandler implements StatementHandler {
protected final Configuration configuration;
protected final ObjectFactory objectFactory;
protected final TypeHandlerRegistry typeHandlerRegistry;
//结果处理器,对数据库返回的结果集(ResultSet)进行封装,返回用户指定的实体类型;
protected final ResultSetHandler resultSetHandler;
//sql占位符处理器,对预编译的SQL语句进行参数设置
protected final ParameterHandler parameterHandler;
//记录执行语句的executor对象
protected final Executor executor;
//sql语句对应的MappedStatement
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();
//一般为写类操作
if (boundSql == null) {
//获得自增主键
generateKeys(parameterObject);
//创建boundSql对象
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
@Override
public BoundSql getBoundSql() {
return boundSql;
}
@Override
public ParameterHandler getParameterHandler() {
return parameterHandler;
}
@Override
//使用模板模式,定义了获取Statement的步骤,其子类实现实例化Statement的具体的方式;
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//通过不同的子类实例化不同的Statement,分为三类:simple(statment)、prepare(prepareStatement)、callable(CallableStatementHandler)
statement = instantiateStatement(connection);
//设置超时时间
setStatementTimeout(statement, transactionTimeout);
//设置数据集大小
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);
}
}
//由子类实现具体的statement
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
//设置超时时间
protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
Integer queryTimeout = null;
if (mappedStatement.getTimeout() != null) {
queryTimeout = mappedStatement.getTimeout();
} else if (configuration.getDefaultStatementTimeout() != null) {
queryTimeout = configuration.getDefaultStatementTimeout();
}
if (queryTimeout != null) {
stmt.setQueryTimeout(queryTimeout);
}
StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
}
//设置fetchSize
protected void setFetchSize(Statement stmt) throws SQLException {
Integer fetchSize = mappedStatement.getFetchSize();
if (fetchSize != null) {
stmt.setFetchSize(fetchSize);
return;
}
Integer defaultFetchSize = configuration.getDefaultFetchSize();
if (defaultFetchSize != null) {
stmt.setFetchSize(defaultFetchSize);
}
}
protected void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
//ignore
}
}
//获得自增主键
protected void generateKeys(Object parameter) {
//获得KeyGenerator对象
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
ErrorContext.instance().store();
//将自增编号到parameter中
keyGenerator.processBefore(executor, mappedStatement, null, parameter);
ErrorContext.instance().recall();
}
}
SimpleStatementHandler Statement的StatementHandler实现类
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);
}
@Override
public int update(Statement statement) throws SQLException {
String sql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
//如果是 Jdbc3KeyGenerator 类型
if (keyGenerator instanceof Jdbc3KeyGenerator) {
//执行写操作
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
//获得更新数量
rows = statement.getUpdateCount();
//执行keyGenerator的后置处理逻辑
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;
}
@Override
public void batch(Statement statement) throws SQLException {
String sql = boundSql.getSql();
statement.addBatch(sql);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();//获取sql语句
statement.execute(sql);//执行sql语句
return resultSetHandler.<E>handleResultSets(statement);//使用resultSetHandler处理查询结果
}
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.<E>handleCursorResultSets(statement);
}
@Override
//使用底层的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();
}
}
@Override
//无需做占位符参数处理
public void parameterize(Statement statement) throws SQLException {
// N/A
}
}
PreparedStatementHandler PreparedStatement 的 StatementHandler 实现类
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);
}
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
//获得更新数目
Object parameterObject = boundSql.getParameterObject();
// 执行 keyGenerator 的后置处理逻辑
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
@Override
public void batch(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//添加到批处理
ps.addBatch();
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
//执行操作
ps.execute();
//处理返回结果
return resultSetHandler.<E> handleResultSets(ps);
}
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleCursorResultSets(ps);
}
@Override
//使用底层的prepareStatement对象来完成对数据库的操作
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
//根据mappedStatement.getKeyGenerator字段,创建prepareStatement
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {//对于insert语句
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
//返回数据库生成的主键
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
//返回数据库生成的主键填充至keyColumnNames中指定的列
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
//设置结果集是否可以滚动以及其游标是否可以上下移动,设置结果集是否可更新
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
//创建普通的prepareStatement对象
return connection.prepareStatement(sql);
}
}
@Override
//使用parameterHandler对sql语句的占位符进行处理
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
}
CallableStatementHandler 不分析
创建StatementHandler对象是在Configuration中
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//创建RoutingStatementHandler对象,实际由statmentType来指定真实的StatementHandler来实现
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
接下来介绍KeyGenerator 主键生成器接口
public interface KeyGenerator {
//sql执行前,order="BEFORE"
void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);
//sql执行后,order="AFTER"
void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);
}
Jdbc3KeyGenerator 适用于MySQL、H2主键生成。
public class Jdbc3KeyGenerator implements KeyGenerator {
//单例模式
public static final Jdbc3KeyGenerator INSTANCE = new Jdbc3KeyGenerator();
@Override
//空实现,因为该类主键都是SQL执行后才生成。
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
// do nothing
}
@Override
//处理返回的自增主键,单个parameter参数可以认为是批量的一个特例
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
processBatch(ms, stmt, getParameters(parameter));
}
public void processBatch(MappedStatement ms, Statement stmt, Collection<Object> parameters) {
ResultSet rs = null;
try {
//获得返回的自增主键
rs = stmt.getGeneratedKeys();
final Configuration configuration = ms.getConfiguration();
final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
//获得keyProperties属性指定的属性名称,表示主键对应的属性名称
final String[] keyProperties = ms.getKeyProperties();
//得到ResultSet的元数据信息
final ResultSetMetaData rsmd = rs.getMetaData();
TypeHandler<?>[] typeHandlers = null;
//检测数据库生成的主键的列数与keyProperties属性指定的列数是否匹配
if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) {
for (Object parameter : parameters) {
if (!rs.next()) {
break;
}
final MetaObject metaParam = configuration.newMetaObject(parameter);
if (typeHandlers == null) {
typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties, rsmd);
}
//将生成的主键设置到用户传入的参数的对应位置
populateKeys(rs, metaParam, keyProperties, typeHandlers);
}
}
} catch (Exception e) {
throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);
} finally {
//关闭ResultSet对象
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
// ignore
}
}
}
}
//将用户传入的实参转换成Collection类型对象
private Collection<Object> getParameters(Object parameter) {
Collection<Object> parameters = null;
if (parameter instanceof Collection) {
parameters = (Collection) parameter;
//如果parameter是map类型,就获取其中的key
} else if (parameter instanceof Map) {
Map parameterMap = (Map) parameter;
if (parameterMap.containsKey("collection")) {
parameters = (Collection) parameterMap.get("collection");
} else if (parameterMap.containsKey("list")) {
parameters = (List) parameterMap.get("list");
} else if (parameterMap.containsKey("array")) {
parameters = Arrays.asList((Object[]) parameterMap.get("array"));
}
}
if (parameters == null) {
parameters = new ArrayList<>();
parameters.add(parameter);
}
return parameters;
}
private TypeHandler<?>[] getTypeHandlers(TypeHandlerRegistry typeHandlerRegistry, MetaObject metaParam, String[] keyProperties, ResultSetMetaData rsmd) throws SQLException {
TypeHandler<?>[] typeHandlers = new TypeHandler<?>[keyProperties.length];
for (int i = 0; i < keyProperties.length; i++) {
if (metaParam.hasSetter(keyProperties[i])) {
Class<?> keyPropertyType = metaParam.getSetterType(keyProperties[i]);
typeHandlers[i] = typeHandlerRegistry.getTypeHandler(keyPropertyType, JdbcType.forCode(rsmd.getColumnType(i + 1)));
} else {
throw new ExecutorException("No setter found for the keyProperty '" + keyProperties[i] + "' in '"
+ metaParam.getOriginalObject().getClass().getName() + "'.");
}
}
return typeHandlers;
}
//将主键参数注入到对象中
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
String property = keyProperties[i];
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
Object value = th.getResult(rs, i + 1);
metaParam.setValue(property, value);
}
}
}
}
SelectKeyGenerator 对于不支持自动生成自增主键的数据库,例如Oracle数据库。
public class SelectKeyGenerator implements KeyGenerator {
public static final String SELECT_KEY_SUFFIX = "!selectKey";
//是否在before阶段执行
private final boolean executeBefore;
//MappedStatement 对象
private final MappedStatement keyStatement;
public SelectKeyGenerator(MappedStatement keyStatement, boolean executeBefore) {
this.executeBefore = executeBefore;
this.keyStatement = keyStatement;
}
@Override
//调用processGeneratedKeys
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
@Override
//调用processGeneratedKeys
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (!executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
try {
//有查询主键的SQL语句,即keyStatement对象非空
if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
String[] keyProperties = keyStatement.getKeyProperties();
final Configuration configuration = ms.getConfiguration();
final MetaObject metaParam = configuration.newMetaObject(parameter);
//创建执行器,类型为SimpleExecutor
if (keyProperties != null) {
Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
//获得SQL语句的查询结果
List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
if (values.size() == 0) {
throw new ExecutorException("SelectKey returned no data.");
} else if (values.size() > 1) {
throw new ExecutorException("SelectKey returned more than one value.");
} else {
//单个主键,将属性设置到parameter中
MetaObject metaResult = configuration.newMetaObject(values.get(0));
if (keyProperties.length == 1) {
if (metaResult.hasGetter(keyProperties[0])) {
setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
} else {
// no getter for the property - maybe just a single value object
// so try that
setValue(metaParam, keyProperties[0], values.get(0));
}
} else {
//多个主键就遍历赋值
handleMultipleProperties(keyProperties, metaParam, metaResult);
}
}
}
}
} catch (ExecutorException e) {
throw e;
} catch (Exception e) {
throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
}
}
//多个主键遍历赋值
private void handleMultipleProperties(String[] keyProperties,
MetaObject metaParam, MetaObject metaResult) {
String[] keyColumns = keyStatement.getKeyColumns();
if (keyColumns == null || keyColumns.length == 0) {
// no key columns specified, just use the property names
for (String keyProperty : keyProperties) {
setValue(metaParam, keyProperty, metaResult.getValue(keyProperty));
}
} else {
if (keyColumns.length != keyProperties.length) {
throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties.");
}
for (int i = 0; i < keyProperties.length; i++) {
setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
}
}
}
private void setValue(MetaObject metaParam, String property, Object value) {
if (metaParam.hasSetter(property)) {
metaParam.setValue(property, value);
} else {
throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
}
}
}