MyBatis SqlSession StatementHandler执行实现原理概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lichunericli/article/details/82563628

Executor的执行步骤:https://blog.csdn.net/lichunericli/article/details/82563667

在Executor的执行步骤中可看出executor.query()方法的最终执行通常是通过SimpleExecutor的doQuery()方法来实现的:
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
BoundSql boundSql) throws SQLException {
   Configuration configuration = ms.getConfiguration();
   // Executor通过StatementHandler的prepare()方法来预编译SQL语句
   StatementHandler handler =  
                    configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
   // 由Statement可看出其底层是通过JDBC来实现的
   Statement stmt = prepareStatement(handler, ms.getStatementLog());
   // Sql的执行处理和结果的封装执行返回都在query中实现
   handler.<E>query(stmt, resultHandler);
   closeStatement(stmt); // 注意内存的溢出,Statement需要在finally中关闭
}

由doQuery源码可以看出StatementHandler的相关处理是在此处实现的。

1. StatementHandler会话处理器生成

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object
parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  StatementHandler statementHandler = // 根据Executor的类型路由,获取对应的StatementHandler类型
   new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);   statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);  // 注意拦截器对底层的影响
  return statementHandler;
}

2. StatementHandler的初始化  
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Connection connection = getConnection(statementLog);  // 通过Transaction获取数据库连接
  // 调用StatementHandler里的prepare方法预编译SQL语句并设置相关Statement参数
  Statement stmt = handler.prepare(connection, transaction.getTimeout());
  // SQL参数的设置,通过ParameterHandler来实现
  handler.parameterize(stmt);
  return stmt;
}   

备注:预编译SQL语句是通过PreparedStatementHandler中的instantiateStatement()方法实现的

3. 预编译SQL语句和Statement参数初始化
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
   // Statement的初始化
   Statement statement = instantiateStatement(connection); 
   // Statement的相关参数设置
   setStatementTimeout(statement, transactionTimeout);
   setFetchSize(statement);
   closeStatement(statement); // 注意Statement的关闭
   return statement; 
}

//  PreparedStatementHandler中实现的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) {
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(),
ResultSet.CONCUR_READ_ONLY);
   } else {
      return connection.prepareStatement(sql);
   }
}

总结:Statement的作用是和数据库进行会话,Executor先调用它的prepare方法预编译SQL语句并设置Statement参数,然后再用ParameterHandler来设置SQL参数以完成预编译,最后通过StatementHandler执行对应的操作,由ResultHandler处理返回结果。

猜你喜欢

转载自blog.csdn.net/lichunericli/article/details/82563628