Springboot项目实现easyExcel批量导入到数据库

Springboot项目实现easyexcel批量导入到数据库

1.导入依赖

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

2. 构建实体类

注意:

  1. 在导入数据的时候 在excel表中的列名顺序要和实体类中的字段顺序一致,它会按照顺序进行一一导入数据,如果顺序不一致,会导致传入的值和字段对应不上的情况;
  2. 如果有字段不需要导入,可以使用注解@ExcelIgnore忽略;
  3. @ExcelProperty中的值也要和excel表中的列名称完全对应;

以下是我的实体类:

@Data
public class LayerMessage {

    private Integer markerId;

    @ExcelProperty("图层名称")
    private String markerName;

    private String descInfo;

    @ExcelProperty("备注")
    private String remark;

    @ExcelProperty("操作时间")
    private Date opDate;

    @ExcelIgnore
    private Integer isDel;

3.Controller层

	@PostMapping(value = "/import")
    @ApiOperation(value = "批量导入")
    public R importLayer(@RequestPart("layerfile") MultipartFile layerfile){
        return layerManagementService.importLayer(layerfile);
    }

若是项目中没有配置swagger不需要写@ApiOperation注解

4.Service层

/**
     * 批量导入
     * @param layerfile
     */
    @Override
    public R importLayer(MultipartFile layerfile) {
        try{
            logger.info("开始导入:{}", layerfile.getOriginalFilename());
//            LayerMessageListener layerMessageListener = new LayerMessageListener();
            layerMessageListener.setRes(new ArrayList<>());
            layerMessageListener.setCount(0);
            EasyExcel.read(layerfile.getInputStream(),LayerMessage.class,layerMessageListener).sheet().doRead();
            return layerMessageListener.resMess();
        }catch (Exception e){
            throw new ValidateException("导入失败");
        }
    }

在service中为了返回详细的错误提示,在读取数据之前,先将存储错误信息的list以set的形式给初始化;在数据插入结束之后调用listener中的函数返回错误信息。
对数据的插入部分我写到了listener中,也可以写到Service中。

Listener文件如下:

@Component
@Scope("prototype")
@Slf4j
public class LayerMessageListener extends AnalysisEventListener<LayerMessage> {

    @Autowired
    private LayerMessageMapper layerMessageMapper;

    /**
     * 每隔100条处理下,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    //计数
    @Setter
    private int count;

    /**
     * 缓存的数据
     */
    private List<Map<Integer,LayerMessage>> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    //导入失败的错误提示集合
    @Setter
    private List<String> res;

    public LayerMessageListener(){
        this.res = new ArrayList<>();
    }

    //一行一行去读取excel内容并封装到LayerMessageDto中
    //默认从第二行读取数据,因为第一行一般都是表头
    @Override
    public void invoke(LayerMessage layerMessage, AnalysisContext analysisContext) {
        //获取行号
        int index=analysisContext.readRowHolder().getRowIndex();

        log.info("解析到第{}行的数据:{}",analysisContext.readRowHolder().getRowIndex(),layerMessage);
        count++;
        //缓存解析的数据
        Map<Integer,LayerMessage> map = new HashMap<>();
        map.put(index,layerMessage);
        cachedDataList.add(map);

        //达到批量处理的数据量,进行批量插入数据库
        if(cachedDataList.size() >= BATCH_COUNT){
            save(cachedDataList);
            //插入完之后清空缓存
            cachedDataList.clear();
        }
    }

    //解析完成后执行收尾工作
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("sheet={} 所有数据解析完成!", analysisContext.readSheetHolder().getApproximateTotalRowNumber()-1);
        //将缓存中剩余的数据保存到数据库中
        save(cachedDataList);
        //清空缓存
        cachedDataList.clear();
    }

    //返回错误信息
    public R resMess(){

        log.info("添加失败{}条数据,count:{}",res.size(),count);
        if(res!=null && res.isEmpty()){
            return R.ok("全部添加成功");
        }else if(res != null && res.size()==count){
            return R.failed(res,"全部添加失败");
        }else{
            return R.failed(res,"部分添加失败");
        }
    }

    //添加数据
    void save(List<Map<Integer, LayerMessage>> layerMessagelist){

		//此处为了将excel中的行号与内容对应起来,我使用了map的结构
        for(Map<Integer,LayerMessage> layerMessagemap:layerMessagelist){
            for(Map.Entry<Integer,LayerMessage> entry:layerMessagemap.entrySet()){
                int rowindex=entry.getKey();
                LayerMessage layerMessage=entry.getValue();

                //此处可以写对excel中导入的内容的校验逻辑

                //检查“markerDataId”是否已经存在于数据库中
                List<String> list = layerMessageMapper.markerDataIdAll();
                List<String> list1 = layerMessageMapper.selectCodeList(layerMessage.getAreaCode());
                if (list1.contains(layerMessage.getAreaCode())){
                    res.add("第"+rowindex+"行错误");
                    continue;
                }
                  
                //将新层消息插入数据库
                layerMessageMapper.insertLayerMessage(layerMessageDto);
            }
        }

    }

}

使用 EasyExcel 实现导入并存储到数据库的功能,可以参考以下步骤: 1. 添加 EasyExcel 依赖 在 pom.xml 文件中添加 EasyExcel 依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.10</version> </dependency> ``` 2. 创建 Excel 实体类 创建一个 Excel 实体类,用于存储 Excel 中的数据。Excel 实体类的属性名称应该与 Excel 中的列名一一对应。 ```java @Data public class User { @ExcelProperty("ID") private Long id; @ExcelProperty("姓名") private String name; @ExcelProperty("年龄") private Integer age; } ``` 3. 创建 Excel 读取监听器 创建一个 Excel 读取监听器,用于处理 Excel 中的每一行数据。在监听器中,可以将读取到的数据转换成实体对象,并将实体对象存储到数据库中。 ```java public class UserExcelListener extends AnalysisEventListener<User> { private UserService userService; public UserExcelListener(UserService userService) { this.userService = userService; } @Override public void invoke(User user, AnalysisContext context) { userService.addUser(user); } @Override public void doAfterAllAnalysed(AnalysisContext context) { // Do nothing } } ``` 4. 创建上传 Excel 的接口 创建一个上传 Excel 的接口,用于接收客户端上传的 Excel 文件,并使用 EasyExcel 解析文件。 ```java @RestController @RequestMapping("/api") public class UserController { private UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), User.class, new UserExcelListener(userService)).sheet().doRead(); return "上传成功"; } } ``` 在上传接口中,首先使用 EasyExcel 读取 Excel 文件,然后将读取到的数据传递给监听器进行处理。 5. 实现 UserService 接口 在 UserService 接口中实现 addUser 方法,用于将读取到的数据存储到数据库中。 ```java public interface UserService { void addUser(User user); } ``` 示例代码: ```java @Service public class UserServiceImpl implements UserService { private UserRepository userRepository; @Autowired public UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public void addUser(User user) { userRepository.save(user); } } ``` 6. 配置数据库连接信息 在 application.properties 中配置数据库连接信息。 ```properties spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 ``` 7. 运行程序并测试 启动应用程序,上传一个包含用户信息的 Excel 文件,程序会将 Excel 中的数据存储到数据库中。 参考代码:https://github.com/alibaba/easyexcel/tree/master/src/test/java/com/alibaba/easyexcel/test/demo/read
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每周都想吃火锅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值