博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mybaits源码分析(八) StatementHandler的详解
阅读量:4074 次
发布时间:2019-05-25

本文共 6416 字,大约阅读时间需要 21 分钟。

    mybaits源码分析(八) StatementHandler的详解

    概述StatementHandler是主要负责处理MyBatis与JDBC之间Statement的交互,通俗而言就是负责操作Statement对象与数据库之间的交互。其执行过程中主要依赖ParameterHandlerResultSetHandler进行参数绑定和结果实体类绑定。

一、类介绍

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) 主线方法

 

public 
List
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());	    List
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)、参数设置好了,就要进行返回值处理,从主线流程handler.<E>query(stmt, resultHandler)继续看。

PreparedStatementHandler 的实现。	 public 
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); }

 2、返回值处理阶段

 从上面可以看到,返回值处理主要是由resultSetHandler处理的。

 

 

结果集处理的过程比较复杂,后续单独再开篇幅讲解!

end!

 

 

    

转载地址:http://pruni.baihongyu.com/

你可能感兴趣的文章
spring boot redis 接入笔记
查看>>
ajax 跨域 session 及 spring boot分布式session
查看>>
spring boot 及 redis 实现分布式session 实践笔记
查看>>
TCP协议与UDP协议的区别
查看>>
SpringMVC与Struts2区别与比较总结
查看>>
get与post区别
查看>>
spring-data-redis序列化实践笔记
查看>>
spring-data-redis使用jdk序列化时increment的异常
查看>>
RPC与其实现方式概念笔记
查看>>
Netty RPC demo 试跑
查看>>
String常量池 及 String StringBuilder StringBuffer 对比 总结得非常好
查看>>
comparator接口与Comparable接口的区别
查看>>
Java中Runnable和Thread以及Callable的区别
查看>>
浅谈sleep方法和wait方法的异同
查看>>
Spring学习之路——单例模式和多例模式
查看>>
库存问题锁的思考
查看>>
"=="和equals方法究竟有什么区别?
查看>>
java中重载与重写的区别
查看>>
Java中继承thread类与实现Runnable接口的区别
查看>>
java 中的final修饰三种类型 or 四种
查看>>