PS:doFlushStatements方法在BaseExecutor中的commit(),rollback(),close()方法中会被调用(即:事务提交,事务回滚,事务关闭三个方法)。

BatchExecutor

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(懒加载时会使用)内的一个内部类,没有任何具体实现,一般我们不会主动去使用。

最后

码字不易,觉得有帮助的可以帮忙点个赞,让更多有需要的人看到

又是一年求职季,在这里,我为各位准备了一套Java程序员精选高频面试笔试真题,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考,需要的可以戳这里免费领取,以下是部分内容截图
字不易,觉得有帮助的可以帮忙点个赞,让更多有需要的人看到**

又是一年求职季,在这里,我为各位准备了一套Java程序员精选高频面试笔试真题,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考,需要的可以戳这里免费领取,以下是部分内容截图

Java程序员面试常问的问题,原来SqlSession只是个甩手掌柜相关推荐

  1. 变态级JAVA程序员面试32问(附答案)(转载)

    flyjimi的专栏 君士坦丁堡的血泪 CSDNBlog  |  我的首页  |  联系作者  |  聚合   |  登录      66篇文章 :: 0篇收藏:: 9篇评论:: 0个Trackbac ...

  2. JAVA程序员面试32问(附答案)(转载)

    为什么80%的码农都做不了架构师?>>>    第一,谈谈final, finally, finalize的区别.  第二,Anonymous Inner Class (匿名内部类) ...

  3. JAVA程序员面试30问(附带答案)

    第一,谈谈final, finally, finalize的区别. 最常被问到.final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能 ...

  4. java程序员封闭_变态级JAVA程序员面试32问(转)

    第一,谈谈final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...

  5. JAVA程序员面试32问(答案)

    第一,谈谈final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...

  6. 变态级JAVA程序员面试32问(转)

    前面部分是问题,后面部分是一些网友给的答案,大家参考吧: ****************************原题部分************************************** ...

  7. :[转贴]变态级JAVA程序员面试32问(附答案

    第一,谈谈final, finally, finalize的区别. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements ...

  8. 应届生就业高峰期,Java程序员面试常犯的5点错误总结

    如今正是毕业生找工作的高峰期,那么在面试Java程序员的过程中会出现什么问题呢?有哪些问题是初入职场的Java程序员在面试中最容易犯的呢?下面,小编总结了Java程序员在面试中不通过的五个原因,作为大 ...

  9. java程序员面试常见面试题及答案整理

    JAVA相关基础知识 1.面向对象的特征有哪些方面  1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分 ...

最新文章

  1. 只需3kbps就能清晰通话,这个谷歌音频工具开源了!
  2. 用曼哈顿距离来巧解---输出菱形的问题
  3. linux之shell编程基本语法
  4. python中的常量是指_python入门教程04-01(python语法入门之变量)
  5. java在线支付---13.java在线支付所有源码:
  6. 多思计组原理虚拟实验室_多思计算机组成原理虚拟实验室
  7. 转载:动态调用WebService(C#)
  8. [LeetCode]319. Bulb Switcher灯泡开关
  9. javweb音乐网站_基于javaweb音乐网站设计与实现
  10. android平板电脑 刷机工具,小白必看,安卓平板电脑刷机教程之一键刷机
  11. python里的jh是啥意思_JH是什么意思啊
  12. 括号配对检测python123_括的拼音_括组词_括意思(解释)-常用汉字大全
  13. Rancher入门到精通-2.0 pening storage failed: block open /prometheus/meta.json: no such file or directory
  14. unity学习———2D人物的移动
  15. RESTful API 笔记整理
  16. ARM汇编----GBLA,GBLL及GBLS
  17. mysql的一些介绍
  18. 支付宝、财付通、快钱 三种功能特点的不同
  19. [unity] Tween和IEnumerator
  20. 信仰崩了?Preact 开始采用 Vue3 的响应式设计

热门文章

  1. 【小游戏】跑酷(带天赋)
  2. 我为什么要做知识星球
  3. 股票量化模型公式操作说明
  4. 用Java输出百钱百鸡的方法及方法数量
  5. ZigBee模块调试_佰亿特
  6. MySQL-客户端连接时的编码问题
  7. ArcGIS制作旅游时间等时圈
  8. STM32CubeMx开发之路—在线升级OTA
  9. 【Excel VBA】控件应用(1)-文本框
  10. java健身房管理系统_基于Java+SSM的健身房俱乐部管理系统、基于Java Web的健身房俱乐部管理系统...