聊聊Mybatis的StatementHandler接口和它的实现类

Posted 周杰伦本人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊Mybatis的StatementHandler接口和它的实现类相关的知识,希望对你有一定的参考价值。

@[TOC]

聊聊Mybatis的StatementHandler接口和它的实现类

今天我们看一下StatementHandler接口和它下面的实现类,这个接口中定义了prepare()方法创建Statement对象,为sql绑定参数的parameterize(),还有一些执行sql的方法,单看接口也看不出来啥,具体看看它的实现类,这下面一共有5个类,咱一一进行介绍一下

路由静态处理器

RoutingStatementHandler

public class RoutingStatementHandler implements StatementHandler 

  private final StatementHandler delegate;

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) 

    switch (ms.getStatementType()) 
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    

    
  

RoutingStatementHandler实现了StatementHandler接口,它有一个成员变量也是StatementHandler接口,而通过它的构造方法可以看出,它会根据MappedStatement的statementType来创建不同的StatementHandler实现类,分别是SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler。而这个类有一个都继承一个类,那就是BaseStatementHandler抽象类:

基础静态处理类

  protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) 
    ....

    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);
  
  protected void generateKeys(Object parameter) 
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    ErrorContext.instance().store();
    keyGenerator.processBefore(executor, mappedStatement, null, parameter);
    ErrorContext.instance().recall();
  

参数处理

在它的构造方法中,parameterHandler是通过ParameterHandler接口的默认实现类DefaultParameterHandler遍历BoundSql的parameterMappings集合,根据参数名获取对应的实参,然后通过typeHandler.setParameter()进行参数绑定,地层利用jdbc的PreparedStatement的set方法

主键生成

还有个generateKeys()方法,这个方法用来生成主键的,通过KeyGenerator的实现来实现的,KeyGenerator有两个方法:processBefore和processAfter,分别是在insert语句执行前获取主键和在insert语句执行后获取主键,KeyGenerator有三个实现类:Jdbc3KeyGenerator、NoKeyGenerator和SelectKeyGenerator,NoKeyGenerator就不多介绍了,就是不生成key,它的两个方法都是空方法,Jdbc3KeyGenerator实现了processAfter()方法,方法比较复杂,主要就是在执行insert语句后把生成的主键保存到实参中,一般我们使用mysql插入数据的时候,主键由数据库生成,而主键数据库生成不了的可以调用SelectKeyGenerator类

首先Mapper文件中定义的<selectKey>标签会被解析成SelectkeyGenerator对象,而SelectkeyGenerator会根据executeBefore属性判断是在insert语句前执行生成主键的方法还是在insert语句之后执行生成主键的方法,而生成主键的过程就是调用processGeneratedKeys()方法,这个方法中会利用Executor执行我们在标中定义的生成主键的sql语句,生成的主键结果保存到MetaObject对象中。

<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
            select LAST_INSERT_ID()
</selectKey>

总结

这篇文章主要讲了StatementHandler接口定义的方法和它的实现类有哪些,RoutingStatementHandler主要起到一个转发的过程,更加不同的statementType创建不同的StatementHandler实例,BaseStatementHandler是抽象类,它的构造方法中有生成主键的逻辑和替换?进行参数绑定的逻辑,SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler都继承这个类

以上是关于聊聊Mybatis的StatementHandler接口和它的实现类的主要内容,如果未能解决你的问题,请参考以下文章

聊聊Mybatis的总体流程

聊聊Mybatis的事务模块

聊聊 MyBatis 缓存

聊聊Mybatis与Spring的整合

Java框架!聊聊MyBatis的历史

聊聊MyBatis缓存机制