1、前景回顾:
前面学习动态 SQL 时,可以使用 foreach 标签插入多条记录,比如:
<insert id="addEmps">
insert into employee(last_name,age,email,dept_id)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.age},#{emp.email},#{emp.department.id})
</foreach>
</insert>
但是上面的 sql 语句并不是批量操作。
2.批量操作:
- 默认的 openSession() 方法没有参数,它会创建有如下特性的
- 会开启一个事务(也就是不自动提交)
- 连接对象会从由活动环境配置的数据源实例得到。
- 事务隔离级别将会使用驱动或数据源的默认设置。
- 预处理语句不会被复用,也不会批量处理更新。
- openSession 方法的 ExecutorType 类型的参数,枚举类型:
- ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情(这是默认装配的)。它为每个语句的执行创建一个新的预处理语句。
- ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
- ExecutorType.BATCH: 这个执行器会批量执行所有更新语句。
@Test
public void testBatch() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//可以执行批量操作的sqlSession
SqlSession openSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
long start = System.currentTimeMillis();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
for (int i = 0; i < 10000; i++) {
mapper.addEmp(new Employee(UUID.randomUUID().toString().substring(0, 5), "b", "1"));
}
openSession.commit();
long end = System.currentTimeMillis();
System.out.println("执行时长:"+(end-start));
//批量:4598
//非批量:10200
}finally{
openSession.close();
}
}
批量与非批量的区别:
- 批量:预编译sql一次 + 设置参数 N 次 + 执行 1 次。
非批量:预编译sql N 次 + 设置参数 N 次 + 执行 N 次.
由此可见批量操作的效率确实非常高。
3.与 Spring 整合:
- 与Spring整合中,我们推荐,额外的配置一个可以专
门用来执行批量操作的sqlSession。
需要用到批量操作的时候,我们可以注入配置的这个批量 SqlSession 。通过他获取到mapper映射器进行操作。
注意:
- 1、批量操作是在 session.commit()以后才发送sql语句给数据库进行执行的
- 2、如果我们想让其提前执行,以方便后续可能的查询操作获取数据,我们可以使用sqlSession.flushStatements()方法,让其直接冲刷到数据库进行执行。