mybatis原理分析(四)---StatementHandler

1.概述

在之前的两篇博客《mybatis原理分析(一)—JDBC》《mybatis原理分析(二)—深入理解Executor》中分别详细的介绍了JDBC的特点和使用以及mybtias中的重要组件Executor,如果不太了解的读者不妨去阅读一下这两篇博客,我相信会给你带来收获。

这两者是通过什么联系起来的呢?

在mybatis中,Executor会创建一个StatementHandler,而JDBC的相关操作全部放到了这个StatementHandler中。

在一次sql会话中,会创建一个Executor,而Executor会根据不同的sql请求,创建不同的StatementHandler去执行JDBC访问数据库。一次会话中三者的数量关系是1:1:N。

2.StatementHandler相关介绍

定义:JDBC处理器,基于JDBC构建JDBC Statement,并设置参数,然后执行Sql。每调用会话当中一次SQl,都会有与之相对应的且唯一的Statement实例。

public interface StatementHandler {
	// 构建一个Statement
  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;
	// 设置参数
  void parameterize(Statement statement)
      throws SQLException;
	// 添加批处理
  void batch(Statement statement)
      throws SQLException;
  // 执行update操作
  int update(Statement statement)
      throws SQLException;
	// 执行query操作
  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;
	// 执行queryCursor操作
  <E> Cursor<E> queryCursor(Statement statement)
      throws SQLException;
	// 获取sql
  BoundSql getBoundSql();
  //获取参数处理器
  ParameterHandler getParameterHandler();

}

类图如下:

在这里插入图片描述

有两个直接的实现类,BaseStatementHandler和RoutingStatementHandler。

BaseStatementHandler 是一个抽象类,并没有实现StatementHandler接口定义的所有的方法,只是实现了它下面三个子类有共性的方法,例如prepare 声明statement,setStatementTimeout 设置超时时间,setFetchSize 设置数据库返回行数等。BaseStatementHandler有三个子类,三个子类分别对应了JDBC中的三种Statement。

RoutingStatementHandler 主要就是用来根据不同的Statement类型选择构建不同的StatementHandler。

3. 构建StatementHandler

在mybatis中是什么时候,又是如何创建StatementHandler的呢?

编写如下测试代码

/**
 * @author gongsenlin
 * @version 1.0
 * @date 2020-09-24 12:56
 */
public class StatementHandlerTest {
  private Configuration configuration;
  private JdbcTransaction jdbcTransaction;

  @Before
  public void init() {
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder
      .build(StatementHandlerTest.class.getResourceAsStream("/mybatis-config.xml"));
    configuration = sessionFactory.getConfiguration();
    jdbcTransaction = new JdbcTransaction(sessionFactory.openSession().getConnection());
  }

  @Test
  public void test1() throws SQLException {
    SimpleExecutor simpleExecutor = new SimpleExecutor(configuration, jdbcTransaction);
    MappedStatement mappedStatement = configuration.
      getMappedStatement("com.gongsenlin.executor.dao.UserMapper.selectByid");
    List<Object> list = simpleExecutor.doQuery(mappedStatement, 10,
      RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, mappedStatement.getBoundSql(10));
  }
}

将断点定位到simpleExecutor.doQuery这一行。进入doQuery方法

在这里插入图片描述

在这个方法里,configuration.newStatementHandler就是用来构建StatementHandler。

在这里插入图片描述

首先会构建一个RoutingStatementHandler
在这里插入图片描述

在它的构造函数里面,就会根据statement的类型,构建对应的StatementHandler。而默认的statement的类型是“PREPARED”

在这里插入图片描述

可以通过添加注解或者xml中配置的方式来修改Statement的类型

在这里插入图片描述
在这里插入图片描述

综上,StatementHandler是在Executor中,执行doQuery或doUpdate等方法的时候,会根据配置的不同类型进行创建不同的StatementHandler,默认是PreparedStatementHandler。

三个子类的逻辑很简单,就是封装了JDBC的操作,了解三个子类的不同点,可以从了解JDBC中三种Statement的不同点开始,可以看看这篇博客《mybatis原理分析(一)—JDBC》

4. 后续

接下来博客更新将会是关于参数处理以及结果集处理相关的内容。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值