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

举报
周杰伦本人 发表于 2022/08/30 13:58:20 2022/08/30
【摘要】 聊聊Mybatis的StatementHandler接口和它的实现类今天我们看一下StatementHandler接口和它下面的实现类,这个接口中定义了prepare()方法创建Statement对象,为sql绑定参数的parameterize(),还有一些执行sql的方法,单看接口也看不出来啥,具体看看它的实现类,这下面一共有5个类,咱一一进行介绍一下 路由静态处理器RoutingSta...

聊聊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都继承这个类

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。