使用场景:
在我们日常开发中,对大量数据通过Excel表导入时需要插入非常多的数据进入数据库,如果使用for循环遍历一条一条插入数据,会大大增加服务器的负载、导致性能下降、资源消耗增加、数据一致性问题以及安全风险增加。为减少服务器负载,使用批量插入数据会大大提升效率、减少资源消耗。在开发过程中尽量少进行接口调用操作。
代码案例:
创建一个DataBaseUtils工具类,将插入数据的处理写在这个类中
- maxInsertItemNumPerTime:一组数据的长度(代码里设为500条数据为一组)
使用方法时传递三个参数:
- list:需要插入的数据列表
- insertFunc:创建的Consumer函数式接口,表示对每个元素执行的操作
- sync:布尔类型,用于判断循环遍历的(parallelStream()方法为无序遍历)
public class DataBaseUtils {
// 数据的长度
private static final int maxInsertItemNumPerTime = 500;
// 使用方法时传递三个参数(list:需要插入的数据列表;insertFunc:创建的Consumer方法;sync:布尔类型,用于判断循环遍历的方式)
public static <T> void batchSplitInsert(List<T> list, Consumer<? super List<T>> insertFunc, boolean sync) {
if (list == null || list.isEmpty()) {
return;
}
List<List<T>> all = new ArrayList<>();
if (list.size() > maxInsertItemNumPerTime) {
int i = 0;
while (i < list.size()) {
List<T> subList;
if (i + maxInsertItemNumPerTime > list.size()) {
subList = list.subList(i, list.size());
} else {
subList = list.subList(i, i + maxInsertItemNumPerTime);
}
i = i + maxInsertItemNumPerTime;
all.add(subList);
}
if (sync) {
all.forEach(insertFunc);
} else {
all.parallelStream().forEach(insertFunc);
}
} else {
insertFunc.accept(list);
}
}
}
写好处理数据方法后,我们可以直接使用这个处理方法进行数据的插入:
- 创建Consumer的函数式接口,进行一组数据的批量插入操作
- 调用数据处理工具类进行函数式接口的调用,实现指定数据条数进行多次批量插入操作
public int insertDemoImport(List<SicClass> list) {
Consumer<List<SicClass>> consumer = o -> demoMapper.insertDemoImport(o);
DataBaseUtils.batchSplitInsert(list, consumer,false);
return list.size();
}
在mybatis中的代码:
<insert id="insertDemoImport" parameterType="java.util.List">
INSERT INTO demo(demo1,demo2,demo3)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.demo1},#{item.demo2},#{item.demons})
</foreach>
</insert>
自此我们便完成了将大量数据以固定数量为一组,按组进行批量插入数据的操作。这个方法不但能快速完成插入操作,相对于for循环遍历,大大降低服务器的负载。