本文共 6416 字,大约阅读时间需要 21 分钟。
mybaits源码分析(八) StatementHandler的详解
概述:StatementHandler是主要负责处理MyBatis与JDBC之间Statement的交互,通俗而言就是负责操作Statement对象与数据库之间的交互。其执行过程中主要依赖ParameterHandler和ResultSetHandler进行参数绑定和结果实体类绑定。一、类介绍
1、StatementHandler的类层级
StatementHandler: 顶级接口, 定义了update、query、parameterize、prepare等方法。 BaseStatementHandler:基础实现,负责创建ParameterHandler和ResultSetHandler。 PreparedStatementHandler:预处理语句实现, SimpleStatementHandler: 简单语句实现, CallableStatementHandler: 存储过程实现。 RoutingStatementHandler: 路由包装,根据不同的类型创建不同的实现作为delegate供实际实现方法调用。 2、构造函数 StatementHandler的构造函数主要是传入了实际执行中需要的一些参数,以及创建了参数处理和结果处理器。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 = mappedStatement.getBoundSql(parameterObject); } this.boundSql = boundSql; // 创建参数处理器 this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); // 创建结果处理器 this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); }
二、执行过程
1、sql语句执行和参数解析阶段
1) 主线方法
publicList doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); // 创建StatementHandler (会根据statement类型创建不同的StatementHandler) StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 预处理语句 stmt = prepareStatement(handler, ms.getStatementLog()); // StatementHandler的query return handler. query(stmt, resultHandler); } finally { closeStatement(stmt); } } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); // 调用StatementHandler的prepare方法 stmt = handler.prepare(connection); // 调用hanlder的parameterize方法 handler.parameterize(stmt); return stmt; }
2) StatementHandler的prepare方法
StatementHandler的prepare方法是BaseStatementHandler中实现,并且调用了instantiateStatement方法
public Statement prepare(Connection connection) throws SQLException { ErrorContext.instance().sql(boundSql.getSql()); Statement statement = null; try { statement = instantiateStatement(connection); setStatementTimeout(statement); setFetchSize(statement); return statement; } } protected Statement instantiateStatement(Connection connection) throws SQLException { String sql = boundSql.getSql(); 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) { // 预编译sql传入不同的resultSet的类型 (遍历方向) return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } else { // 预编译sql return connection.prepareStatement(sql); } }
prepare 方法就是实际上调用connection.prepareStatement的封装
3) StatementHandler的parameterize方法public void parameterize(Statement statement) throws SQLException { // 调用parameterHandler设置参数 parameterHandler.setParameters((PreparedStatement) statement); } public void setParameters(PreparedStatement ps) throws SQLException { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); ListparameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { // 遍历parameterMappings for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; // 得到每个属性名称 String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // 从Additional中取属性值 value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { // 如果有类型处理器,就直接设置为外部原始参数 value = parameterObject; } else { // 反射获取值 MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); // jdbcType是供空值使用的,需要传递类型 JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull(); // preparedStatement设置参数 typeHandler.setParameter(ps, i + 1, value, jdbcType); } } } }
4)、参数设置好了,就要进行返回值处理,从主线流程handler.<E>query(stmt, resultHandler)继续看。
PreparedStatementHandler 的实现。 public2、返回值处理阶段List query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.execute(); // 强转成预编译语句,执行execute然后交由结果处理器处理结果。 return resultSetHandler. handleResultSets(ps); } SimpleStatementHandler 的实现 public List query(Statement statement, ResultHandler resultHandler)throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); //直接执行sql return resultSetHandler. handleResultSets(statement); }
从上面可以看到,返回值处理主要是由resultSetHandler处理的。
结果集处理的过程比较复杂,后续单独再开篇幅讲解! end!
转载地址:http://pruni.baihongyu.com/