mybatis源码阅读-执行器StatementHandle和ParameterHandler(五)
StatementHandle
类图
各个实现类的作用
SimpleStatementHandler 用于使用Statement操作数据库(不会使用参数化查询?)
PreparedStatementHandler 用于使用PreparedStatement操作数据库(会使用参数化查询)
CallableStatementHandler 用于使用CallableStatement 操作数据库(主要是执行存储过程)
RoutingStatementHandler 待定
StatementHandler调用时机
Executor部分代码
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; int var6; try { Configuration configuration = ms.getConfiguration(); /*获得对应的statementHandler 可以是SimpleStatementHandler PreparedStatementHandler CallableStatementHandler
* 没有动态传boundSql内部会根据MappedSatatement的getBoundSql获取boundSql 内部是通过MappedStatement的sqlSource获取BoundSql 有静态sql 动态sql几种实现
*/ StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null); //通过StaementHandler设置参数 stmt = this.prepareStatement(handler, ms.getStatementLog()); //调用update方法获得返回结果 内部使用Statement操作数据库 var6 = handler.update(stmt); } finally { this.closeStatement(stmt); } return var6; }
SimpleStatementHandler
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); } /** * 通过Staement执行修改 * @param statement * @return * @throws SQLException */ public int update(Statement statement) throws SQLException { //获得sql语句 boundSql接口 根据MapperStatement获得 String sql = this.boundSql.getSql(); Object parameterObject = this.boundSql.getParameterObject(); KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator(); int rows; if (keyGenerator instanceof Jdbc3KeyGenerator) { statement.execute(sql, 1); rows = statement.getUpdateCount(); keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject); } else if (keyGenerator instanceof SelectKeyGenerator) { statement.execute(sql); rows = statement.getUpdateCount(); keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject); } else { statement.execute(sql); rows = statement.getUpdateCount(); } return rows; } public <E> Cursor<E> queryCursor(Statement statement) throws SQLException { String sql = this.boundSql.getSql(); statement.execute(sql); return this.resultSetHandler.handleCursorResultSets(statement); } //根据connection创建Statement protected Statement instantiateStatement(Connection connection) throws SQLException { return this.mappedStatement.getResultSetType() != null ? connection.createStatement(this.mappedStatement.getResultSetType().getValue(), 1007) : connection.createStatement(); } //设置参数 由于Staement不支持?参数化查询 sql语句写死参数 所以实现是空的 public void parameterize(Statement statement) throws SQLException { } }
PreparedStatementHandler
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; ps.execute(); int rows = ps.getUpdateCount(); Object parameterObject = this.boundSql.getParameterObject(); KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator(); keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject); return rows; } //根据connection创建PrepareStatement protected Statement instantiateStatement(Connection connection) throws SQLException { String sql = this.boundSql.getSql(); if (this.mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) { String[] keyColumnNames = this.mappedStatement.getKeyColumns(); return keyColumnNames == null ? connection.prepareStatement(sql, 1) : connection.prepareStatement(sql, keyColumnNames); } else { return this.mappedStatement.getResultSetType() != null ? connection.prepareStatement(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareStatement(sql); } } //设置参数 public void parameterize(Statement statement) throws SQLException { //交给parameterHandler处理parameterHandler是根据MappedStatement中获得 this.parameterHandler.setParameters((PreparedStatement)statement); } }
参数设置是委托给ParameterHandler处理的
CallableStatementHandler
public class CallableStatementHandler extends BaseStatementHandler { public CallableStatementHandler(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 { CallableStatement cs = (CallableStatement)statement; cs.execute(); int rows = cs.getUpdateCount(); Object parameterObject = this.boundSql.getParameterObject(); KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator(); keyGenerator.processAfter(this.executor, this.mappedStatement, cs, parameterObject); this.resultSetHandler.handleOutputParameters(cs); return rows; } //根据连接创建 CallStatement protected Statement instantiateStatement(Connection connection) throws SQLException { String sql = this.boundSql.getSql(); return this.mappedStatement.getResultSetType() != null ? connection.prepareCall(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareCall(sql); } //设置参数 public void parameterize(Statement statement) throws SQLException { this.registerOutputParameters((CallableStatement)statement); this.parameterHandler.setParameters((CallableStatement)statement); } }
ParameterHandler
类图
DefaultParameterHandler
public class DefaultParameterHandler implements ParameterHandler { private final TypeHandlerRegistry typeHandlerRegistry; private final MappedStatement mappedStatement; private final Object parameterObject; private BoundSql boundSql; private Configuration configuration; public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { this.mappedStatement = mappedStatement; this.configuration = mappedStatement.getConfiguration(); this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); this.parameterObject = parameterObject; this.boundSql = boundSql; } public Object getParameterObject() { return this.parameterObject; } public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId()); //获得BoundSql里面的ParameterMapping 内部保存的是参数的映射 List<ParameterMapping> parameterMappings = this.boundSql.getParameterMappings(); if (parameterMappings != null) { for(int i = 0; i < parameterMappings.size(); ++i) { ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { String propertyName = parameterMapping.getProperty(); Object value; if (this.boundSql.hasAdditionalParameter(propertyName)) { value = this.boundSql.getAdditionalParameter(propertyName); } else if (this.parameterObject == null) { value = null; } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) { value = this.parameterObject; } else { MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject); value = metaObject.getValue(propertyName); } //获得对应的TypeHandler TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = this.configuration.getJdbcTypeForNull(); } try { //给Statement设置参数 typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException var10) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var10, var10); } catch (SQLException var11) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var11, var11); } } } } } }
StatementHandler设置
可选类型
public enum StatementType { STATEMENT, PREPARED, CALLABLE }
xml设置
<select id="findAllStudents" resultMap="StudentResult" statementType="STATEMENT"> SELECT * FROM STUDENTS </select>