文档章节

Mybatis3.3.x技术内幕(五):Executor之doFlushStatements()

祖大俊
 祖大俊
发布于 2016/04/29 23:11
字数 858
阅读 1822
收藏 14

这天气,热的我满头大蒜。

在上一篇博文《五鼠闹东京之执行器Executor设计原本》中,已经对Executor做了比较详细的分析,但是,测试妹纸阅读完后,表示某些地方看不懂,毫不客气的给我提出了两点修改意见。

一、看完你的Statement和PrepareStatement批处理原理图,依然不明白为何一个编译Sql 3次,而另外一个编译Sql 1次。

二、对关闭Statement对象一笔带过,不够清晰。

我准备亡羊补牢,针对上面的两个问题进行补充完善。



1.Statement和PrepareStatement在批处理时对Sql的编译策略

insert into students(id) values(1);
insert into students(id) values(1);
insert into students(id) values(2);
insert into students(id) values(3);

上面的4个Sql,无论是Statement,还是PrepareStatement,对Sql都编译3次。因为其中第1、2条Sql是完全相同的,只会编译1次。

insert into students(id) values(?); // id=[1,2,3]

对于PrepareStatement,支持问号“?”占位符,向数据库中插入id=[1,2,3]三条记录,对Sql只编译1次,由于减少了编译次数,大幅提高了效率。

Statement不支持问号“?”占位符,向数据库中插入id=[1,2,3]三条记录,只能写成下面这样。

insert into students(id) values(1);
insert into students(id) values(2);
insert into students(id) values(3);

由于Sql不同,所以编译3次,效率较低。

以上讨论,是在批处理情况下,二者的编译Sql表现。



2.doFlushStatements()

ReuseExecutor.doFlushStatements()。

  @Override
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    for (Statement stmt : statementMap.values()) {
      closeStatement(stmt);
    }
    statementMap.clear();
    return Collections.emptyList();
  }

Reuse的Statement内,并没有未执行的Sql命令,所以直接close即可。



BatchExecutor.doFlushStatements()。

@Override
  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    try {
      List<BatchResult> results = new ArrayList<BatchResult>();
      if (isRollback) {
        return Collections.emptyList();
      }
      for (int i = 0, n = statementList.size(); i < n; i++) {
        Statement stmt = statementList.get(i);
        BatchResult batchResult = batchResultList.get(i);
        try {
          // executeBatch()
          batchResult.setUpdateCounts(stmt.executeBatch());
          //...
        results.add(batchResult);
      }
      return results;
    } finally {
      for (Statement stmt : statementList) {
        closeStatement(stmt);
      }
      currentSql = null;
      statementList.clear();
      batchResultList.clear();
    }
  }

BatchExecutor内保存的Statement对象内,都是有等待执行的Sql批处理命令的,所以,先执行stmt.executeBatch(),保存执行结果,然后再close。


Executor的实现类中,只有ReuseExecutor和BatchExecutor缓存了Statement对象,所以,其他的Executor对doFlushStatements()进行了空实现。


3.flushStatements()调用时机时序图

(Made In Visual Paradigm)

即,每当调用commit、rollback、close方法时,都会先调用doFlushStatements(),然后再commit、rollback、close。

上图同样适用于其他的Executor实现类。


结语:设计原则中,有一条是“单一职责”原则,受其启发,博文也采取“单一职责”原则,一篇博文尽量分析一类知识点,避免跳跃性晕眩。

另外,大牛黄勇先生,搞了一个smartweb项目,大牛红薯先生,搞了一个J2Cache项目,大牛罗果先生,更是搞了一个高大上的Tiny项目……,羡慕崇拜之余,还是静下心来,夯实基础,希望以后咱也能体验下大牛的无敌最寂寞。


版权提示:文章出自开源中国社区,若对文章感兴趣,可关注我的开源中国社区博客(http://my.oschina.net/zudajun)。(经过网络爬虫或转载的文章,经常丢失流程图、时序图,格式错乱等,还是看原版的比较好)

© 著作权归作者所有

共有 人打赏支持
祖大俊
粉丝 748
博文 32
码字总数 52477
作品 0
昌平
私信 提问
Mybatis3.3.x技术内幕(四):五鼠闹东京之执行器Executor设计原本

在上一篇博文中,已经分析了Mybatis事务相关的内容,而今天的这篇博文,很多内容都是在方法method内部,与事务无关,所以,建议暂时忘记事务概念,避免搅扰。 Mybatis对数据库的操作,都将委...

祖大俊
2016/04/27
1K
2
Mybatis3.3.x技术内幕(一):SqlSession和SqlSessionFactory列传

前言:我长大了,成年了,有需求,但我单身,所以我要讨个媳妇,要求是:漂亮、高挑、身材好、笑容甜美…… 和A相亲:漂亮,不够高挑。 和B相亲:高挑,身材不够好。 和C相亲:身材好,笑容不...

祖大俊
2016/04/25
3.3K
2
Mybatis3.3.x技术内幕(十五):Mybatis之foreach批量insert,返回主键id列表(修复Mybatis返回null的bug)

Mybatis在执行批量插入时,如果使用的是for循环逐一插入,那么可以正确返回主键id。如果使用动态sql的foreach循环,那么返回的主键id列表,可能为null,这让很多人感到困惑;本文将分析问题产...

祖大俊
2016/05/13
9.6K
17
Mybatis3.3.x技术内幕(六):StatementHandler(Box stop here)

神通广大的猴哥SqlSession,把琐事委托给二弟Executor来处理,二弟Executor可不那么傻,于是它又把事情委托给三弟StatementHandler,三弟憨厚老实,本着Box stop here的精神,无怨无悔不说,...

祖大俊
2016/04/30
1K
3
Mybatis#BaseExecutor源码解析

BaseExecutor是Executor的一个子类,是一个抽象类,实现接口Executor的部分方法,并提供了三个抽象方法 doUpdate doFlushStatements doQuery 在他的子类SimpleExecutor、ReuseExecutor和Bat...

芥末无疆sss
2018/10/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如果让你写一个消息队列,该如何进行架构设计?

面试题 如果让你写一个消息队列,该如何进行架构设计?说一下你的思路。 面试官心理分析 其实聊到这个问题,一般面试官要考察两块: 你有没有对某一个消息队列做过较为深入的原理的了解,或者...

李红欧巴
今天
4
0
错题

无知的小狼
今天
2
0
PowerShell因为在此系统中禁止执行脚本的解决方法

参考:window系统包管理工具--chocolatey 报错提示: & : 无法加载文件 C:\Users\liuzidong\AppData\Local\Temp\chocolatey\chocInstall\tools\chocolateyInstall.ps1,因为在此系统上禁止运...

近在咫尺远在天涯
今天
3
0
TP5 跨域请求处理

https://blog.csdn.net/a593706205/article/details/81774987 https://blog.csdn.net/wyk9916/article/details/82315700...

15834278076
今天
3
0
深入理解java虚拟机-Java内存区域与内存溢出异常

深入理解java虚拟机 Java内存区域与内存溢出异常 运行时数据区域 程序计数器 线程私有,内存小,是当前线程执行的字节码行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行...

须臾之余
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部