easyexcel读取excel将数据存到mysql【一个简单的例子】

读取excel

1 xml里面增加maven

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>

2 读取excel用到的实体

自行更改字段

package com.hahaha.dto;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@EqualsAndHashCode
public class ReadExcelDto {

    /**
     * 账期
     * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
     */
    @ExcelProperty("账期")
    private String month;

	/**
     * 强制读取第三列 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
     */
    @ExcelProperty(index = 2)
    private Double doubleData;
   
    /**
     * 姓名
     */
    @ExcelProperty(value = "姓名")
    private String name;
}

3 读取excel用到的监听器

package com.hahaha.util.easyexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.hahaha.service.CommonExcelReadService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 公共的excel读取监听器
 * @param <T> 实体范型
 */
public class CommonReadListener<T> extends AnalysisEventListener<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(CommonReadListener.class);
    /**
     * 每隔1000条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 1000;
    List<T> list = new ArrayList<>();
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private CommonExcelReadService service;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param service 公共 service
     */
    public CommonReadListener(CommonExcelReadService service) {
        this.service = service;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        Integer num = service.saveBatchData(list);
        LOGGER.info("存储数据库成功数量为:{}", num);
    }
}

将数据都读取到内存中的监听器

package com.hahaha.util.easyexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 公共的excel读取监听器
 * @param <T> 实体范型
 */
public class CommonReadListener2<T> extends AnalysisEventListener<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(CommonReadListener2.class);

    List<T> list = new ArrayList<>();

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

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 获取excel的所有数据,数据量太大会出现内存溢出
     * @return list
     */
    public List<T> getList() {
        return list;
    }

}

4 读取excel用到的公共service

package com.hahaha.service;

import java.util.List;

/**
 *
 * 公共的excel读取接口
 * 实现接口并重写saveBatchData方法即可保存自定义的业务数据
 */
public interface CommonExcelReadService {

    /**
     * 批量保存数据
     * @param list 要保存的数据
     * @param <T> 数据类型实体,可以根据具体的业务实体转换
     * @return Integer 保存成功的条数
     */
    public <T> Integer saveBatchData(List<T> list);
}

5 读取excel用到的公共方法

package com.hahaha.util.easyexcel;

import com.alibaba.excel.EasyExcel;
import com.hahaha.service.CommonExcelReadService;

import java.io.InputStream;

/**
 * excel工具类
 */
public class EasyExcelUtil {

    /**
     * 这种是 内存溢出出现的情况非常低,但是事务不好控制(主要是出错全部回滚)
     * @param inputStream 文件流
     * @param clazz 读取excel的实体class
     * @param commonService 将数据存储到某张表的service【需要在业务service上实现这个接口,并重写saveBatchData方法】
     * @param <T> 泛型类型
     */
    public static <T> void readExcel(InputStream inputStream, Class<?> clazz, CommonExcelReadService commonService) {
        CommonReadListener readExcelDataListener = new CommonReadListener(commonService);

        EasyExcel.read(inputStream, clazz, readExcelDataListener)
                .sheet()
                .doRead();
    }
    
    /**
     * 这种是 将数据都读取到内存中
     * 事务好控制,但是数据量太大绝对会出现内存溢出
     * @param inputStream 文件流
     * @param clazz 读取excel的实体class
     * @param <T> 泛型类型
     */
    public static <T> List<T> readExcel(InputStream inputStream, Class<?> clazz) {
        CommonReadListener2 readExcelDataListener = new CommonReadListener2();

        EasyExcel.read(inputStream, clazz, readExcelDataListener)
                .sheet()
                .doRead();

        return readExcelDataListener.getList();
    }
}

6

controller接口

package com.hahaha.controller;

import javax.annotation.Resource;
import com.hahaha.util.easyexcel.EasyExcelUtil;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class MyController {

	@Resource
    private MyService myService;

	@PostMapping("upload")
    public 你的返回结构 upload(MultipartFile file) {
    	// 校验文件格式和大小的
        CommonMethod.uploadVerify(file);
        try {
        // todo ReadExcelDto是读取excel的dto,改成自己的;myService改成自己的
            EasyExcelUtil.readExcel(file.getInputStream(), ReadExcelDto.class, myService);
        } catch (IOException o){
            log.error(o.getMessage());
            返回错误信息
        }
        return 返回正确信息
    }
}

校验文件格式和大小看这个
https://blog.csdn.net/lh155136/article/details/126585728

7 业务service和serviceIml

我这个是有mybatisplus的,如果不需要可以去掉

package com.hahaha.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.hahaha.entity.MyEntity;
import com.hahaha.service.CommonExcelReadService;

// todo 这里非常重要,一定要实现CommonExcelReadService 
public interface MyService extends IService<MyEntity>, CommonExcelReadService {

}
package com.hahaha.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hahaha.dto.ReadExcelMIITDto;
import com.hahaha.entity.MyEntity;
import com.hahaha.mapper.MyMapper;
import com.hahaha.service.MyService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
public class MyServiceImpl extends ServiceImpl<MyMapper, MyEntity> implements MyService {

    @Resource
    private MyMapper myMapper;

    @Override
    public <T> Integer saveBatchData(List<T> list) {
        List<ReadExcelDto> entityList = JSONObject.parseArray(JSONObject.toJSONString(list),
                ReadExcelDto.class);

        return myMapper.saveBatchList(entityList);
    }
}

7 mapper和mapper.xml

我是手写了一个insertbatch方法,也可以用mybaits-plus的savebatch

package com.hahaha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hahaha.dto.ReadExcelMIITDto;
import com.hahaha.entity.MyEntity;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface MyMapper extends BaseMapper<MyEntity> {

    int saveBatchList(List<ReadExcelDto> list);
}
	<insert id="saveBatchList">
        INSERT INTO 你的表名字 (
            month,
            name
        )
        VALUES
        <foreach collection="list" item="obj" separator=",">
            (
                #{obj.month},
                #{obj.name}
            )
        </foreach>
	</insert>

测试

在这里插入图片描述

在这里插入图片描述
其他难度的后面再更新,有疑问的欢迎评论

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,可以给你提供一个思路。 首先,需要在SpringBoot中引入EasyExcel的依赖,可以通过以下方式在pom.xml文件中添加: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.9</version> </dependency> ``` 接着,需要编写一个Controller来接收上传的Excel文件,并读取其中的内容,解析MySQL建表语句并返回字符串。可以参考以下代码: ```java @RestController public class ExcelController { @PostMapping("/upload") public String uploadExcel(@RequestParam("file") MultipartFile file) throws IOException { // 读取Excel文件 InputStream inputStream = file.getInputStream(); ExcelReader excelReader = new ExcelReader(inputStream, null, new ExcelListener()); excelReader.read(); // 获取解析出来的建表语句 List<String> createTableSqls = ExcelListener.getCreateTableSqls(); // 将建表语句拼接成一个字符串返回 StringBuilder sb = new StringBuilder(); for (String createTableSql : createTableSqls) { sb.append(createTableSql).append("\n"); } return sb.toString(); } /** * EasyExcel的监听器,用于解析Excel内容并生成建表语句 */ public static class ExcelListener extends AnalysisEventListener<List<String>> { private static List<String> createTableSqls = new ArrayList<>(); private static final String TABLE_NAME_PREFIX = "table_"; private static final String COLUMN_NAME_PREFIX = "col_"; @Override public void invoke(List<String> rowData, AnalysisContext context) { // 生成建表语句 String tableName = TABLE_NAME_PREFIX + context.getCurrentSheet().getSheetNo(); StringBuilder sb = new StringBuilder(); sb.append("CREATE TABLE ").append(tableName).append(" (\n"); for (int i = 0; i < rowData.size(); i++) { String columnName = COLUMN_NAME_PREFIX + i; sb.append(" ").append(columnName).append(" VARCHAR(255)"); if (i != rowData.size() - 1) { sb.append(","); } sb.append("\n"); } sb.append(");"); createTableSqls.add(sb.toString()); } @Override public void doAfterAllAnalysed(AnalysisContext context) { // 解析完成后清空缓存 createTableSqls.clear(); } public static List<String> getCreateTableSqls() { return createTableSqls; } } } ``` 上面的代码中,我们定义了一个ExcelListener类作为EasyExcel的监听器,用于解析Excel内容并生成建表语句。在Controller中,我们将上传的Excel文件读取并交给ExcelListener来处理,最终将生成的建表语句拼接成一个字符串返回。 需要注意的是,上面的代码中生成的建表语句只是一个示例,具体的生成规则需要根据实际情况进行修改。 希望这个思路能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值