Mybatis-批量插入

Oracle数据库批量插入

对于Oracle数据库,批量插入的写法如下。
首先,先对要批量插入的对象设置ID的值,一般是通过序列获取。这样我们自然也就拿到了插入后的主键id。

1
2
@Select(" SELECT SEQ_TEST.NEXTVAL AS ID FROM DUAL")
long getSeqID();

然后在XML文件中写 insert 语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<insert id="batchInsert" parameterType="com.lzumetal.database.employee">
INSERT INTO EMPLOYEE (
ID, NAME, PHONE, EMAIL, GENDER
)
<!-- list是传进来的参数的名称 -->
<foreach collection="list" item="item" separator="UNION ALL">
(SELECT
#{item.id, jdbcType=BIGINT},
#{item.name, jdbcType=VARCHAR},
#{item.phone, jdbcType=VARCHAR},
#{item.email, jdbcType=VARCHAR},
#{item.gender, jdbcType=INTEGER}
FROM DUAL
)
</foreach>
</insert>

MySQL数据库批量插入

MySQL数据库的批量插入写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO EMPLOYEE (
ID, NAME, PHONE, EMAIL, GENDER
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.id, jdbcType=BIGINT},
#{item.name, jdbcType=VARCHAR},
#{item.phone, jdbcType=VARCHAR},
#{item.email, jdbcType=VARCHAR},
#{item.gender, jdbcType=INTEGER}
)
</foreach>
</insert>

Mapper.java文件中代码是这样写的:

1
2
3
4
5

@Mapper
public interface EmployeeMapper {
void batchInsert(@Param("list") List<Employee> list);
}

注意,对于Oracle数据库,批量插入或者查询都可能导致参数变量过多而报错。查看oracle11 的官方文档,明确说明变量的数量不能超过64k(64k=64*1024B=65536B)。16位的2进制最大的数字,即1111111111111111,换算成10进制就是65536,那么我们计算可以插入的条数 n=65536/变量数。
因此需要在Serivce层中对传参数量做下限制,比如批量插入可以写成这样,一次最多只插入200条记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import com.google.common.collect.Lists;


public void batchAdd1(List<Book> books) {
int toIndex;
int capacity = 200;
List<Book> tempHolder;
for (int i = 0; i <= books.size() / capacity; i++) {
toIndex = (i + 1) * capacity;
tempHolder = books.subList(i * capacity, Math.min(toIndex, books.size()));
bookMapper.batchInsert(tempHolder);
}
}


public void batchAdd2(List<Book> books) {
List<List<Book>> partition = Lists.partition(books, 200);
for (List<Book> partionBooks:partition) {
bookMapper.batchInsert(partionBooks);
}
}
------ 本文完 ------