投标文件网站开发技术部分,广东东莞区号,长春做网站团队,无锡市锡山建设局网站有时候要从第三方导入数据#xff0c;一般量都比较大#xff0c;除了方法用异步线程Async之外#xff0c;如果每条记录都调用一次save显然对数据库压力很大。可以使用JPA的批量保存方法saveAll(Iterable entities)。由于JPA的批量保存和批量修改是同一个方法#xff0c;所以…有时候要从第三方导入数据一般量都比较大除了方法用异步线程Async之外如果每条记录都调用一次save显然对数据库压力很大。可以使用JPA的批量保存方法saveAll(Iterable entities)。由于JPA的批量保存和批量修改是同一个方法所以本文也适用批量修改操作。一、Entity改造增加3个注解方便在Controller类build方式构造对象。BuilderNoArgsConstructorAllArgsConstructor完整注解DataBuilderNoArgsConstructorAllArgsConstructorApiModel(休息日休息日可能不处理业务备用)EntityTable(name bz_setup_restday, schema bankrouter)public class BzSetupRestdayEntity implements Serializable {......二、Repositorypackage com.pay.payee.repository;import com.pay.payee.entity.BzSetupRestdayEntity;import org.springframework.data.jpa.repository.JpaRepository;import java.util.Date;/***休息日休息日可能不处理业务备用(BzSetupRestday)表数据库访问层** author 郭秀志 jbcode126.com* since 2020-05-08 23:50:43*/public interface BzSetupRestdayRepository extends JpaRepository {}三、Service实现类关键方法saveAll(Iterable entities)。package com.pay.payee.service.impl;import com.pay.payee.entity.BzSetupRestdayEntity;import com.pay.payee.repository.BzSetupRestdayRepository;import com.pay.payee.service.IBzSetupRestdayService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.Date;import java.util.List;import java.util.Optional;/***休息日休息日可能不处理业务备用(BzSetupRestday)表服务实现类** author 郭秀志 jbcode126.com* since 2020-05-08 23:50:43*/Service(bzSetupRestdayService)public class BzSetupRestdayServiceImpl implements IBzSetupRestdayService {Autowiredprivate BzSetupRestdayRepository bzSetupRestdayRepository;Overridepublic void save(BzSetupRestdayEntity bzSetupRestdayEntity) {bzSetupRestdayRepository.save(bzSetupRestdayEntity);}public List saveAll(Iterable entities) {return bzSetupRestdayRepository.saveAll(entities);}}四、Controller60000条数据使用方法saveAll(Iterable entities)进行批量保存。package com.pay.payee.controller;import com.pay.payee.entity.BzSetupRestdayEntity;import com.pay.payee.service.IBzSetupRestdayService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.ArrayList;import java.util.Date;import java.util.List;/*** 休息日休息日可能不处理业务备用(BzSetupRestday)表控制层** author 郭秀志 jbcode126.com* since 2020-05-08 23:50:43*/RestControllerRequestMapping(/bzSetupRestday)public class BzSetupRestdayController {/*** 服务对象*/Resourceprivate IBzSetupRestdayService bzSetupRestdayService;/** Description 批量保存* Param [entities]* return java.util.List*/GetMapping(/saveAll)public List saveAll() {long begin System.currentTimeMillis();List list new ArrayList();for (int i 0; i 60000; i) {BzSetupRestdayEntity build BzSetupRestdayEntity.builder().groupId(1).restDate(new Date()).useType(2).build();list.add(build);}List sList (List) bzSetupRestdayService.saveAll(list);long end System.currentTimeMillis();System.out.println(时长 (end - begin));return sList;}}五、调用url测试http://localhost:8555/bzSetupRestday/saveAll控制台输出耗时(毫秒)时长15958网上个别人遇到saveAll速度慢添加了如下配置信息解决。我实测速度无差别。springjpa:properties:hibernate:#打印执行时间统计信息generate_statistics: truejdbc:#每批500条提交batch_size: 500batch_versioned_data: trueorder_inserts: trueorder_updates: true六、批量保存优化6.1 背景有次实践是有20万左右的数据要批量的插入速度非常慢发现打印出来的sql是先select一次再insert。6.2 速度慢原因原生的saveAll()方法可以保证程序的正确性但是如果数据量比较大效率低看下源码就知道其原理是 for 循环每一条数据然后先select一次如果数据库存在则update。如果不存在则insert。6.3. saveAll源码SimpleJpaRepository的saveAll(Iterable entities)方法源码如下Transactionalpublic List saveAll(Iterable entities) {Assert.notNull(entities, Entities must not be null!);List result new ArrayList();Iterator var3 entities.iterator();while(var3.hasNext()) {S entity var3.next();result.add(this.save(entity));//save方法是核心逻辑}return result;}Transactionalpublic S save(S entity) {if (this.entityInformation.isNew(entity)) {this.em.persist(entity);return entity;} else {return this.em.merge(entity);}}6.4 解决方案6.4.1 批量插入解决方案是自己用em进行持久化插入省了一步查询操作。PersistenceContextprivate EntityManager entityManager;OverrideTransactional(rollbackFor Exception.class)public void addBatch(List list) {for (ProjectApplyDO projectApplyDO : list) {entityManager.persist(projectApplyDO);//insert插入操作}entityManager.flush();entityManager.clear();}6.4.2 批量更新在确保数据已经存在的情况下如果是批量更新可以如下代码代替上面的entityManager.persist(projectApplyDO);语句entityManager.merge(projectApplyDO);//update更新操作