说明
用到的框架
RuoYi-Vue: 🎉 基于 SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本
https://gitee.com/y_project/RuoYi-Vue
关键 dependency
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.3</version> </dependency>
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency>
|
通过 excel 进行导入
注:以下均为为简要说明,完整示例请获取完整代码。
com.ruoyi.prevention.controller.PopulationController.java
1 2 3 4 5 6 7 8 9
| @PostMapping("/importData") public R<String> importData(@RequestParam(value="file") MultipartFile file) throws Exception { if (file == null) { logger.info("file is null"); } final PopulationExcelReadListener readListener = new PopulationExcelReadListener(populationMapper); EasyExcel.read(file.getInputStream(), DailyNucleicInputExcel.class, readListener).doReadAll(); return R.ok("已导入" + readListener.getEffectRows() + "条记录"); }
|
com.ruoyi.prevention.utils.PopulationExcelReadListener 进行数据的校验和获取数据并入库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class PopulationExcelReadListener implements ReadListener<DailyNucleicInputExcel> {
private static final int BATCH_COUNT = 500;
private final List<PopulationDO> cachedResidentDataList = new ArrayList<>(BATCH_COUNT);
private final PopulationMapper mapper;
public PopulationExcelReadListener(PopulationMapper mapper) { this.mapper = mapper; }
@Override public void invoke(DailyNucleicInputExcel excelData, AnalysisContext context) { }
@Override public void doAfterAllAnalysed(AnalysisContext context) { } }
|
com.ruoyi.prevention.mapper.PopulationMapper 接口声明
1 2 3 4 5 6 7
|
long insertResidentBatch(List<PopulationDO> list);
|
src\main\resources\mapper\prevention\PopulationMapper.xml
这里选择 foreach 批量插入效率高。目前从接口测试 50 万条数据耗时 100 秒上下。另外可按实际需要是否搭配 ON DUPLICATE KEY UPDATE 进行覆盖插入。另外请根据需要是否要启用多线程进行插入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <insert id="insertResidentBatch" parameterType="java.util.List"> INSERT IGNORE INTO population (card_number, name, tel, district , town, community, addr, detail_addr, update_time ) VALUES <foreach collection="list" item="it" separator=","> ( #{it.cardNumber}, #{it.name}, #{it.tel}, #{it.district} , #{it.town}, #{it.community}, #{it.addr}, #{it.detailAddr}, #{it.updateTime} ) </foreach> ON DUPLICATE KEY UPDATE
name = values(name), tel = values(tel), district = values(district),
town = values(town), community = values(community), addr = values(addr), detail_addr = values(detail_addr), update_time = values(update_time) </insert>
|
通过 json 进行导入
com.ruoyi.prevention.controller.PopulationController.java
和通过 excel 进行类型,直接将前端传入的 json 数据进行校验去重过滤等操作后直接存入数据库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @PostMapping("/importDataByJson") public R<String> insertBatch(@RequestBody final DailyNucleicInputExcel[] array) { logger.info("importDataByJson ---: 导入 json 人员信息条目数 = {}", array.length); final Date timeStampDate = new Date(); final List<PopulationDO> dailyNucleicDOList = Arrays.stream(array) .filter(DailyNucleicInputExcel::nameIsNotNull) .filter(DailyNucleicInputExcel::cardNumberIsValid) .filter(DailyNucleicInputExcel::notContainsServiceArea) .distinct() .map(it -> PopulationFactory.newInstance(it, timeStampDate)) .collect(Collectors.toList()); final long effectRows = this.populationService.insertResidentBatch(dailyNucleicDOList); return R.ok("已导入" + array.length + "条记录"); }
|
com.ruoyi.prevention.service.PopulationService
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public long insertResidentBatch(List<PopulationDO> populationDOList) { final int size = populationDOList.size(); final int batchSize = 500; int used = 0; long inserts = 0; while (used < size) { int step = Math.min(size - used, batchSize); long before = System.currentTimeMillis(); inserts += this.populationMapper.insertResidentBatch(populationDOList.subList(used, used + step)); this.logger.debug("插入耗时:" + (System.currentTimeMillis() - before) + "毫秒"); used += step; } return inserts; }
|
导出人员信息到 excel
1 2 3 4 5 6 7
| @PostMapping("/export") public void export(HttpServletResponse response, @RequestBody PopulationListInputVO inputVO) throws UnsupportedEncodingException { final EasyExcelUtil<PopulationOutputVO> easyExcelUtil = new EasyExcelUtil<>(PopulationOutputVO.class); easyExcelUtil.exportEasyExcel(response, populationQueryList, this.sheetName); }
|