Mybaits source code analysis (eight) Detailed Explanation of StatementHandler

    Mybaits source code analysis (eight) Detailed Explanation of StatementHandler


    Overview : StatementHandler is mainly responsible for handling the interaction of Statement between MyBatis and JDBC. Generally speaking, it is responsible for operating the interaction between Statement object and database. The execution process mainly relies on ParameterHandler and ResultSetHandler for parameter binding and result entity class binding.

One, class introduction

1. The class level of
    
    StatementHandler StatementHandler : the top-level interface, which defines methods such as update, query, parameterize, prepare, etc.
    
    BaseStatementHandler : Basic implementation, responsible for creating ParameterHandler and ResultSetHandler.
    
    PreparedStatementHandler : prepared statement implementation,
    
    SimpleStatementHandler : simple statement implementation,
    
    CallableStatementHandler : stored procedure implementation.
    
    RoutingStatementHandler : routing packaging, according to different types to create different implementations as a delegate for the actual implementation method to call.
    
    2. Constructor The constructor of
      StatementHandler mainly passes in some parameters needed in actual execution, and creates parameter processing and result processors.

  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);
	  }

    Second, the execution process

    1. sql statement execution and parameter parsing stage

     1) Main line method
 

 public <E> List<E> 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.<E>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) Prepare method of StatementHandler

     The prepare method of StatementHandler is implemented in BaseStatementHandler, and the instantiateStatement method is called

  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);
	    }
	  }

     The prepare method actually calls the encapsulation of connection.prepareStatement

 3) the parameterize method of StatementHandler

 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());
	    List<ParameterMapping> parameterMappings = 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). After the parameters are set, return value processing must be performed. Continue from the main line process handler.<E>query(stmt, resultHandler).

	 PreparedStatementHandler 的实现。
	 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
	    PreparedStatement ps = (PreparedStatement) statement;
	    ps.execute(); // 强转成预编译语句,执行execute然后交由结果处理器处理结果。
	    return resultSetHandler.<E> handleResultSets(ps); 
	  }
	
	 SimpleStatementHandler 的实现
	
	  public <E> List<E> query(Statement statement, ResultHandler resultHandler)throws SQLException {
	    String sql = boundSql.getSql();
	    statement.execute(sql); //直接执行sql
	    return resultSetHandler.<E>handleResultSets(statement);
	  }


 2. Return value processing stage

 As you can see from the above, the return value processing is mainly handled by resultSetHandler.

 

 

The process of result set processing is more complicated, so I will explain it separately in the follow-up!
end!

 

 


    

Guess you like

Origin blog.csdn.net/shuixiou1/article/details/113732826