java 批量导入数据(新增、更新)

备注:

两种方法:批量修改,新增 application.yml //允许多条数据,否则mybatis 插入数据报错

&allowMultiQueries=true

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://ip地址:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=trueusername: 账号password: 密码

(1)方法一
通过id等唯一性字段比较,获取updateList 和 insertList

  List<String> list = operationLogService.getAllIdList();List<OperationLog> updList = new ArrayList<>();List<OperationLog> insertList = new ArrayList<>();for (int i =0 ; i < operationLogs.size(); i++) {OperationLog temp = operationLogs.get(i);if (list.contains(String.valueOf(temp.getId())) ){updList.add(temp);} else {insertList.add(temp);}}boolean b = false;if(insertList.size() > 0){List<List<OperationLog>> listIns = ListUtil.averageAssign(insertList, 1000);for(List<OperationLog> list1: listIns) {b = operationLogService.batchInsert(list1);}}if(updList.size() > 0 ){List<List<OperationLog>> listUpd = ListUtil.averageAssign(updList, 500);for(List<OperationLog> list2: listUpd) {b = operationLogService.batchUpdate(list2);}}
	List 集合拆分
public static <T> List<List<T>> averageAssign(List<T> source, int splitItemNum) {List<List<T>> result = new ArrayList<List<T>>();if (source != null && source.size() > 0 && splitItemNum > 0) {if (source.size() <= splitItemNum) {// 源List元素数量小于等于目标分组数量result.add(source);} else {// 计算拆分后list数量int splitNum = (source.size() % splitItemNum == 0) ? (source.size() / splitItemNum) : (source.size() / splitItemNum + 1);List<T> value = null;for (int i = 0; i < splitNum; i++) {if (i < splitNum - 1) {value = source.subList(i * splitItemNum, (i + 1) * splitItemNum);} else {// 最后一组value = source.subList(i * splitItemNum, source.size());}result.add(value);}}}return result;}

第二种办法

经过测试,批量更新比较慢,可以优化为 先删后全部插入的方案,提高相应时间

  List<String> list = operationLogService.getAllIdList();List<Integer> updList = new ArrayList<>();for (int i =0 ; i < operationLogs.size(); i++) {OperationLog temp = operationLogs.get(i);if (list.contains(String.valueOf(temp.getId())) ){updList.add(temp.getId());}}boolean b = false;if(updList.size() > 0 ){operationLogService.removeByIds(updList);}if(operationLogs.size() > 0){List<List<OperationLog>> listIns = ListUtil.averageAssign(operationLogs, 1000);for(List<OperationLog> list1: listIns) {b = operationLogService.batchInsert(list1);}}

第三种方案

	采用线程池批量执行,进一步提高执行速度
public boolean threadMethod(List<OperationLog> updateList) {boolean res = false;// 初始化线程池,、ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 60,4, TimeUnit.SECONDS, new ArrayBlockingQueue(10), new ThreadPoolExecutor.CallerRunsPolicy());// 大集合拆分成N个小集合、try{List<List<OperationLog>> splitNList = ListUtil.averageAssign(updateList, 100);// 记录单个任务的执行次数CountDownLatch countDownLatch = new CountDownLatch(splitNList.size());// 对拆分的集合进行批量处理, 先拆分的集合, 再多线程执行for (List<OperationLog> singleList : splitNList) {// 线程池执行threadPool.execute(new Thread(new Runnable(){@Overridepublic void run() {if (singleList.size() > 0) {operationLogService.batchUpdate(singleList);// 任务个数 - 1, 直至为0时唤醒await()countDownLatch.countDown();}}}));}countDownLatch.await();res = true;}catch (Exception e){res = false;e.printStackTrace();}finally {threadPool.shutdown();}return res;}

附录,其他模块
mapper

  boolean batchInsert(List<OperationLog> list);boolean batchUpdate(List<OperationLog> list);

xml

<select id="getAllIdList"  resultType="String" >select id from xxx order by idselect><insert id="batchInsert" parameterType="com.highguard.sct.auditModule.entity.OperationLog">insert into xxx (id, user_name, ...)values<foreach collection="list" item="item" separator=",">(#{item.id}, #{item.userName}, ...)foreach>insert><update id="batchUpdate" parameterType="com.highguard.sct.auditModule.entity.OperationLog"><foreach collection="list" item="item" index="index" separator=";">update xxx set<if test="item.userName != null and item.userName !=''">user_name = #{item.userName},if><if test="item.userRole != null and item.userRole !=''">user_role = #{item.userRole},if>...createtime = #{item.createtime}<where>id = #{item.id}where>foreach>update>

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

item集合中每一个元素进行迭代时的别名, index表示在迭代过程中,每次迭代到的位置, open该语句以什么开始,
separator在每次进行迭代之间以什么符号作为分隔 符, close以什么结束,
在使用foreach的时候最关键的也是最容易出错的就是collection属性, 该属性是必须指定的,但是在不同情况
下,该属性的值是不一样的, 主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了

insert into shop_coupon_record( id, coupon_id, pick_date_time, use_date_time, member_id, is_use, create_date_time, delete_status ) select #{item.id}, #{item.couponId}, #{item.pickDateTime}, #{item.useDateTime}, #{item.memberId}, #{item.isUse}, #{item.createDateTime}, #{item.deleteStatus} from dual


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部