mybatis批量插入有三种方式:

  1. 反复执行单条插入语句
  2. xml拼接sql
  3. 批处理执行
反复执行单条插入语句
@Test
public void testInsertBatch2() throws Exception {
    long start = System.currentTimeMillis();
    User user;
    SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(false);
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    for (int i = 0; i < 500; i++) {
        user = new User();
        user.setId("test" + i);
        user.setName("name" + i);
        user.setDelFlag("0");
        mapper.insert(user);
    }
    sqlSession.commit();
    long end = System.currentTimeMillis();
    System.out.println("---------------" + (start - end) + "---------------");
}
xml拼接sql

这种方式就是利用xml拼接sql语句,因此种方式经常会受限于sql缓存大小的限制,比如mysql的限制为1M

<insert id="insertBatch">
    INSERT INTO t_user (id, name, del_flag)
    VALUES
    <foreach collection ="list" item="user" separator =",">
         (#{user.id}, #{user.name}, #{user.delFlag})
    </foreach >
</insert>

foreach 的主要作用在构建 in 条件中,它可以在 sql 语句中进行迭代一个集合。foreach 元素的属性主要有 collection,item,separator,index,open,close。

  1. collection:指定要遍历的集合。表示传入过来的参数的数据类型。该属性是必须指定的,要做 foreach 的对象。在使用 foreach 的时候最关键的也是最容易出错的就是 collection 属性。在不同情况 下,该属性的值是不一样的,主要有一下 3 种情况: a. 如果传入的是单参数且参数类型是一个 List 的时候,collection 属性值为 list。 b. 如果传入的是单参数且参数类型是一个数组的时候,collection 的属性值为 array。 c. 如果传入的参数是多个的时候,就需要把它们封装成 Map,当然单参数也可以封装成 Map。Map 对象没有默认的键。
  2. item:表示集合中每一个元素进行迭代时的别名。将当前遍历出的元素赋值给指定的变量,然后用#{变量名},就能取出变量的值,也就是当前遍历出的元素。
  3. separator:表示在每次进行迭代之间以什么符号作为分隔符。select * from tab where id in(1,2,3)相当于1,2,3之间的","
  4. index:索引。index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置。遍历 list 的时候 index 就是索引,遍历 map 的时候 index 表示的就是 map 的 key,item 就是 map 的值。
  5. open/close:表示该语句以什么开始/结束。

使用方式

@Test
public void testInsertBatch() throws Exception {
    long start = System.currentTimeMillis();
    List<User> list = new ArrayList<>();
    User user;
    for (int i = 0; i < 10000; i++) {
        user = new User();
        user.setId("test" + i);
        user.setName("name" + i);
        user.setDelFlag("0");
        list.add(user);
    }
    userService.insertBatch(list);
    long end = System.currentTimeMillis();
    System.out.println("---------------" + (start - end) + "---------------");
}
批处理执行

接口定义和普通的接口一致

<insert id="insert">
    INSERT INTO t_user (id, name, del_flag) VALUES(#{id}, #{name}, #{delFlag})
</insert>

批处理执行模式

@Test
public void testInsertBatch2() throws Exception {
    long start = System.currentTimeMillis();
    User user;
    //开启批处理模式
    SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    for (int i = 0; i < 500; i++) {
        user = new User();
        user.setId("test" + i);
        user.setName("name" + i);
        user.setDelFlag("0");
        mapper.insert(user);
    }
    sqlSession.commit();
    long end = System.currentTimeMillis();
    System.out.println("---------------" + (start - end) + "---------------");
}