SpringBoot+Mybatis-plus整合EasyExcel批量导入Excel到数据库+导出Excel

  发布时间:2025-11-05 04:16:47   作者:玩站小弟   我要评论
一、前言今天小编带大家一起整合一下easyExcel​,之所以用这个,是因为easyExcel​性能比较好,不会报OOM!市面上常见的导入导出Excel分为三种:hutooleasyExcelpoih 。

一、批量前言

今天小编带大家一起整合一下easyExcel​,导入之所以用这个,数据是库导因为easyExcel​性能比较好,不会报OOM!批量

市面上常见的导入导入导出Excel分为三种:

hutooleasyExcelpoi

hutool和easyExcel​都是对poi​的封装,使用起来更加方便!数据

二、库导导入依赖

小编这里是批量3.0.X版本的,版本不同可能导致部分有出入,导入如果大家版本是数据3.1.X,可以去官方文档看看有不一样的库导!

官方文档:https://easyexcel.opensource.alibaba.com/

复制<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version></dependency>1.2.3.4.5.

三、批量实体类

这里可以自带的导入转换器:

@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")LocalDateTimeStringConverter

或者自定义转化器:实现:implements Converter<T>。

具体文档:官方文档:https://easyexcel.opensource.alibaba.com/docs/3.0.x/quickstart/read#%E6%97%A5%E6%9C%9F%E6%95%B0%E5%AD%97%E6%88%96%E8%80%85%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2

@ExcelProperty参数注意:

这里不建议 index 和 name 同时用,数据要么一个对象只用index,要么一个对象只用name去匹配。

用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据。源码下载

复制/** * @author wangzhenjun * @date 2022/12/2 15:52 */@Datapublic class Test

{

@TableId private Integer id

;

@ExcelProperty(index = 0

)

private String name

;

@ExcelProperty(index = 1

)

private Integer age

;

@ExcelProperty(index = 2,converter = LocalDateTimeStringConverter.class

)

private LocalDateTime time

;

}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.

四、编写监听器

注意点:这个监听器一定不要是单例的,被spring管理默认为单例,如果要使用​@Component​,一定要加上:@Scope("prototype")​,这样在创建完后spring不会进行管理,每次都会是新bean!不加​@Component​在导入时要进行new ImportDataListener!小编这里不想new了直接这样写!!如果不想这样,可以使用构造器set进行使用!BATCH_COUNT​:数据阈值,超过了就会清理list,在之前可以进行保存到数据库中,方便内存回收,防治OOM!这里保存到数据库中一般使用​批量保存,不要解析到一行就去保存数据库中,这样数据量大会给数据库增加IO,导致挂掉!这里小编使用ServiceImpl的saveBatch()方法,也可以自己写一下,像小编这样写,会出现循环依赖,高防服务器加上@Lazy就行!

复制/** * @author wangzhenjun * @date 2022/12/2 15:38 */@Slf4j@Component// 每次bean都是新的,不要单例@Scope("prototype"

)

public class ImportDataListener implements ReadListener<Test>

{

@Autowired @Lazy private TestService testService

;

/** * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 100

;

/** * 缓存的数据 */ private List<Test> importExcelDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT

);

/** * 这个每一条数据解析都会来调用 * * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(Test data, AnalysisContext context

) {

log.info("解析到一条数据:{}", JSON.toJSONString(data

));

importExcelDataList.add(data

);

// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (importExcelDataList.size() >= BATCH_COUNT

) {

saveData

();

// 存储完成清理 list importExcelDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT

);

}

}

/** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context

) {

// 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData

();

log.info("所有数据解析完成!"

);

}

/** * 加上存储数据库 */ private void saveData

() {

log.info("{}条数据,开始存储数据库!", importExcelDataList.size

());

testService.saveBatch(importExcelDataList

);

log.info("存储数据库成功!"

);

}

}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.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.

五、Controller

复制/** * @author wangzhenjun * @date 2022/10/26 16:51 */@Slf4j@RestController@RequestMapping("/test"

)

public class TestController

{

@Autowired private TestService testService

;

@PostMapping("/import"

)

public Result importExcel(@RequestBody MultipartFile multipartFile

){

testService.importExcel(multipartFile

);

return Result.success("ok"

);

}

}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

六、Service

复制/** * @author wangzhenjun * @date 2022/10/26 16:55 */public interface TestService extends IService<Test>

{

void importExcel(MultipartFile multipartFile

);

}1.2.3.4.5.6.7.

七、ServiceImpl

复制/** * @author wangzhenjun * @date 2022/10/26 16:56 */@Servicepublic class TestServiceImpl extends ServiceImpl<TestDbMapper, Test> implements TestService

{

@Autowired private ImportDataListener importDataListener

;

@SneakyThrows @Override public void importExcel(MultipartFile multipartFile

) {

InputStream inputStream = multipartFile.getInputStream

();

// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(inputStream, Test.class, importDataListener).sheet().doRead

();

}

}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

八、Mapper

复制/** * @author wangzhenjun * @date 2022/10/26 17:07 */public interface TestDbMapper extends BaseMapper<Test>

{

}1.2.3.4.5.6.

九、测试

准备Excel数据:

postman上传:

控制台打印:

数据库查看:

完美搞定!!

十、总结

这样就完成了easyExcel批量导入Excel到数据库,还是有很多要注意的香港云服务器点:

自定义转换器监听器不要单例保存数据库采用批量版本差距
  • Tag:

相关文章

最新评论