BatchExecutor从名字上也可以看出来,这是一个支持批量操作的执行器。

如果说大家都用过jdbc就知道,jdbc是支持批量操作的,有一个executeBatch()方法用来执行批量操作,但是有一个前提就是执行批量操作的sql除了参数不同,其他都应该是相同的(关于这一点,下面我们会举例来说明)。 需要注意的是,批量操作只支持insert,update,delete语句,select语句是不支持的,所以BatchExecutor内的doQuery方法和其他执行器并没有很大不同,区别就是在查询之前会先调用flushStatements(),我们不做过多讨论,主要看一下doUpdate方法:

下面是一些成员属性:

这个方法的逻辑就是判断相同模式的sql会共用同一个Statement对象,然后缓存到list内,需要注意的是它只会和前一个进行比对,也就是说假如你有相同模式的2条sql,但是你中间先执行了一条其他sql,那么就会产生3个Statement对象,从而无法共用了。

PS:上面的doUpdate中返回了一个数:BATCH_UPDATE_RETURN_VALUE,这个数其实没有什么特别含义,只需要返回一个没有意义的负数就可以,表示代码不知道执行成功多少条。比如说直接返回-1,或者干脆直接返回Integer.MIN_VALUE都是没有问题的,全凭个人喜好了。

接下来我们再看看doFlushStatements()方法:

这个方法就是去遍历上面存储好的Statement,依次调用Statement中的executeBatch方法。

三种常用批量插入方式

讲到这里,我们就干脆扯开一点,聊一聊MyBatis编程中常用的三种批量操作方式。

直接代码循环

这是最简单的一种,但也是效率最低的一种,如下简单示例:


UserAddressMapper userAddressMapper = session.getMapper(UserAddressMapper.class);
for (UserAddress userAddress : userAddressList){userAddressMapper.insert(userAddress); }

这种方式会把大部分时间消耗在网络连接通信上,一般不建议使用。

利用MyBatis中批量标签foreach处理

新建测试类:


package com.lonelyWolf.mybatis.batch;
import com.lonelyWolf.mybatis.mapper.UserAddressMapper;
import com.lonelyWolf.mybatis.model.UserAddress;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class TestBatchInsert {public static void main(String[] args) throws IOException {String resource = "mybatis-config.xml";//读取mybatis-config配置文件InputStream inputStream = Resources.getResourceAsStream(resource);//创建SqlSessionFactory对象SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建SqlSession对象SqlSession session = sqlSessionFactory.openSession();try {List<UserAddress> userAddressList = new ArrayList<>();UserAddress userAddr = new UserAddress();userAddr.setAddress("广东深圳");userAddressList.add(userAddr);UserAddress userAddr2 = new UserAddress();userAddr2.setAddress("广东广州");userAddressList.add(userAddr2);UserAddressMapper userAddressMapper = session.getMapper(UserAddressMapper.class);userAddressMapper.batchInsert(userAddressList);session.commit();}finally {session.close();}}
}

Mapper接口新增如下方法:


int batchInsert(List<UserAddress> userAddresses);

XML文件如下:


<insert id="batchInsert">insert into lw_user_address (address) values<foreach collection="list" item="item" separator=",">(#{item.address})       </foreach></insert>

执行之后输出如下语句:

顺便我们介绍一下foreach标签的用法:

  • collection 表示待循环的对象。当参数为List时,默认"list",参数为数组时,默认"array"。但是当我们在Mapper接口中使用@Param(“xxx”)时,默认的list,array将会失效,必须使用我们自己设置的参数名。 还有一种特殊情况就是假如集合里面有集合或者对象里面有集合,那么可以使用collection=“xxx.属性名”。

  • item 表示当前循环中的元素。

  • open/close,表示循环体开始和结束位置插入的符号,一般成对出现,in语句使用较多,如:


<select id="test">select * from xxx where id in <foreach collection="list" item="item" open="(" close=")" separator=",">#{item.xxx}     </foreach></select>
  • separator:表示每个循环之后的分割符号,可参考上面的例子

  • index:当前元素在集合的下标,如果是map则是map的key值,这个参数一般用的相对较少。

BatchExecutor插入

我们把上面的普通例子中获取Session的例子改写一下:

``

SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);

``

然后执行之后输出sql如下:

可以看到,这两条语句就是相同模式的sql,只是参数不同,所以直接执行一次。

我们把上面的例子改写一下:


UserAddress userAddr = new UserAddress();
userAddr.setAddress("广东深圳");
userAddr.setId(1);
userAddressList.add(userAddr);UserAddress userAddr2 = new UserAddress();
userAddr2.setAddress("广东广州");
userAddr2.setId(2);
userAddressList.add(userAddr2);UserAddressMapper userAddressMapper = session.getMapper(UserAddressMapper.class);
userAddressMapper.insert(userAddr);//sql-1
userAddressMapper.insert10(userAddr2);//sql-10
userAddressMapper.insert(userAddr);//sql-1

insert和insert10分别对应如下语句(一条是1个参数,一条是2个参数):


<insert id="insert" parameterType="com.lonelyWolf.mybatis.model.UserAddress" useGeneratedKeys="true" keyProperty="address">insert into lw_user_address (address) values (#{address})</insert><insert id="insert10" parameterType="com.lonelyWolf.mybatis.model.UserAddress" useGeneratedKeys="true" keyProperty="address">insert into lw_user_address (id,address) values (#{id},#{address})</insert>

上面就是有两种sql模型,理论上应该执行2次,但是我们根据源码知道,因为insert语句中间被insert10隔开了,所以实际上sql-1也是不能复用的,也就是会执行3次:

PS:这三种批量执行的效率有兴趣的可以自己去测试一下,效率最高的应该是foreach标签的形式,网上有其他

ClosedExecutor

ClosedExecutor是ResultLoaderMap(懒加载时会使用)内的一个内部类,没有任何具体实现,一般我们不会主动去使用。

CachingExecutor

这个执行器和缓存有关,在这里我们先不展开,下一篇讲述缓存实现原理的时候再来分析

StatementHandler

最后

光给面试题不给答案不是我的风格。这里面的面试题也只是凤毛麟角,还有答案的话会极大的增加文章的篇幅,减少文章的可读性,因此仅以截图展示,需要的小伙伴可以点击这里即可免费获取!

Java面试宝典2021版

最常见Java面试题解析(2021最新版)

2021企业Java面试题精选

存中…(img-lCrku9xU-1628616767609)]

最常见Java面试题解析(2021最新版)

[外链图片转存中…(img-sjWokVXd-1628616767610)]

[外链图片转存中…(img-69YFMT4o-1628616767611)]

2021企业Java面试题精选

[外链图片转存中…(img-GJYdLUof-1628616767612)]

原来SqlSession只是个甩手掌柜,看完我工资从12K变成了20K相关推荐

  1. Java,看完我工资从12K变成了20K

    三.ASCII可显示字符 二进制 十进制 十六进制 图形 0010 0000 32 20 (空格)(␠) 0010 0001 33 21 ! 0010 0010 34 22 " 0010 0 ...

  2. 看完我工资从12K变成了20K!被腾讯辞退的高级Android工程师现在怎么了?Android篇

    前言 之前老是看着搞Java的朋友炫耀他的核心知识点笔记,真的,我内心毫无波澜,只有一点点酸 其实Android开发也有很多知识点,我一直以来就想要一份Android核心知识点笔记来帮助自己查漏补缺, ...

  3. 看完涨薪2K+_____2019 JAVA 必刷面试题

    欢迎大家加入我的github项目,一起学习,一起发展 ---> 全栈工程师进阶学习站 ---> 我的前端学习笔记 --->行业内最新最群的报告,工作日每日更新 ->原生 js ...

  4. 原来SqlSession只是个甩手掌柜?真正干活的是谁?

    点击上方蓝色字体,选择"标星公众号" 优质文章,第一时间送达 关注公众号后台回复pay或mall获取实战项目资料+视频 作者:双子孤狼 blog.csdn.net/zwx90010 ...

  5. 【MyBatis系列7】原来SqlSession只是个甩手掌柜,真正干活的却是Executor等四大对象

    Executor原理分析 前言 MyBatis架构分层 Executor BaseExecutor SimpleExecutor ReuseExecutor BatchExecutor 三种常用批量插 ...

  6. 洛神说看完这篇Mybatis一二级缓存要是你还不会,就送你个学妹!skr

    人世仙家本自殊,何须相见向中途.惊鸿瞥过游龙去,漫恼陈王一事无. 嗨,大家好,我是洛神,性别男.一个来自快乐星球的程序员. 欢迎大家专注我的公众号[程序员洛神],不仅分享技术,还会分享生活趣事.体育. ...

  7. 电脑总有安装计算机更新,为什么我们的电脑总会莫名的安装垃圾软件,看完吓一跳,欢迎关注...

    现在电脑已经走进了我们的生活,很多人都已经接触电脑了,然而对于电脑的使用,我们除了知道那些最常见的使用方式之外,大多数人对电脑的其他功能任然是一无所知,当然学习电脑专业和IT的除外了,很多人应该都会发 ...

  8. 据说看完这21个故事的人,30岁前都成了亿万富翁。你是下一个吗?

    1.甲去买烟,烟29元,但他没火柴,跟店员说:"顺便送一盒火柴吧."店员没给. 乙去买烟,烟29元,他也没火柴,跟店员说:"便宜一毛吧."最后,他用这一毛买一盒 ...

  9. 200字带你看完一本书,GPT-3已经会给长篇小说写摘要了

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 文 | 博雯 源 | 量子位 现在,AI能帮你200字看完一段12万 ...

最新文章

  1. eclipse下对中文乱码问题的一些思考
  2. python中json和字典相互转化
  3. tf.control_dependencies()函数用法
  4. zip,tar,打包并压缩
  5. Modbus网口设备接入多比物联网云平台教程
  6. 廉价raid_如何查找80行代码中的廉价航班
  7. 蓝桥杯2015初赛-奖券数目-枚举
  8. 【Spark Summit East 2017】使用Spark MLlib和Apache Solr构建实时实体类型识别系统
  9. MVC公司架构介绍——自运行任务
  10. 火线精英手游服务器维护,火线精英手机版登录失败进不去解决办法
  11. 券商IT的建设一定要有全局观、前瞻性,要走在业务前面,而不是被动响应
  12. Plc编程入门基础知识,在短时间内如何学会编程
  13. StringUtil.isNotEmpty(转)
  14. PSP ISO游戏运行必备工具:ISO TOOL 1.970 功能一览图文教程
  15. IMDB 2003 07 12 最新排名
  16. css样式,鼠标移动上去变成禁用、小手等样式。
  17. 微信渐变国旗头像来了!一键生成
  18. J-LINK放了一晚,不能识别,灯一直闪
  19. 你还不了解的OKRs-E是什么?
  20. 禁用wordpress5.2自动裁剪图片功能

热门文章

  1. 最小二乘回归函数(单变量)
  2. matlab smooth原理,Matlab smooth函数原理
  3. 仿小红书根据图片高度自适应viewpager高度轮播图
  4. 为什么计算机无法读取u盘,为什么usb连接电脑读不出u盘呢?
  5. SQL导入excel用---EXCEL如何批量添加逗号
  6. “智能语音助手”的竞品分析 —— 你好小悟小爱同学(3)
  7. HTML在一段文字下加虚线,怎么定义每一行的文字下面都有下划线虚线?_html/css_WEB-ITnose...
  8. [Other]计算机组成原理分解实验:实验一 基本逻辑门逻辑实验
  9. Joomla安装设置教程(转)
  10. 贷后管理3大流程,专业术语及指标解析​