Mybaitsソースコード分析(8)StatementHandlerの詳細な説明

    Mybaitsソースコード分析(8)StatementHandlerの詳細な説明


    概要StatementHandlerは、主にMyBatisとJDBC間のStatementの相互作用の処理を担当します。一般的に、Statementオブジェクトとデータベース間の相互作用の操作を担当します。実行プロセスは、主にパラメータバインディングと結果エンティティクラスバインディングParameterHandlerResultSetHandlerに依存しています。

1つ、クラス紹介

1.
    
    StatementHandlerのクラスレベルStatementHandler:更新、クエリ、パラメータ化、準備などのメソッドを定義する最上位のインターフェイス。
    
    BaseStatementHandler:基本的な実装。ParameterHandlerとResultSetHandlerの作成を担当します。
    
    PreparedStatementHandler:プリペアドステートメントの実装、
    
    SimpleStatementHandler:シンプルなステートメントの実装、
    
    CallableStatementHandler:ストアドプロシージャの実装。
    
    RoutingStatementHandler:呼び出す実際の実装メソッドのデリゲートとしてさまざまな実装を作成するための、さまざまなタイプに応じたルーティングパッケージ。
    
    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)メインライン方式
 

 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)StatementHandlerのメソッドを準備します

     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());
	    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)パラメータを設定した後、戻り値の処理を行う必要があります。メインラインのプロセスハンドラから続行します。<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.戻り値の処理段階

 上記からわかるように、戻り値の処理は主にresultSetHandlerによって処理されます。

 

 

結果セット処理のプロセスはより複雑なので、フォローアップで個別に説明します!
終わり!

 

 


    

おすすめ

転載: blog.csdn.net/shuixiou1/article/details/113732826