EasyExcel을 사용하여 로컬 Excel 데이터를 읽고 mysql 데이터베이스로 가져오기

이 글은 EasyExcel의 읽기(읽기)만 기록합니다.

1. EasyExcel은 무엇을 합니까?

먼저 EasyExcel에 대한 설명을 살펴보겠습니다:
EasyExcel은 Alibaba에서 오픈 소스로 제공하는 Excel 처리 프레임워크입니다.Java 기반의 Excel을 읽고 쓰기 위한 간단하고 메모리 절약형 오픈 소스 프로젝트입니다. EasyExcel이 메모리 사용량을 크게 줄일 수 있는 주된 이유는 Excel을 파싱할 때 모든 파일 데이터를 한 번에 메모리에 로드하는 것이 아니라 디스크에서 데이터를 한 줄씩 읽어서 하나씩 파싱하기 때문입니다.

오픈소스 주소:
깃허브 주소: https://github.com/alibaba/easyexcel
(코드만 봐도 아직 좀 헷갈리네요. 샤오포역에서 관련 영상 찾아봤는데 크레이지갓 영상에 명쾌하게 설명되어 있네요. . 거의 직접 그가 말한 대로 하십시오. 물론 실제 상황에 따라 적절하게 변경해야 합니다.)

2. 프로젝트 배경

내가 만든 작은 프로젝트는 엑셀 테이블의 데이터를 데이터베이스로 가져와야 하는데 일부 데이터 열에는 [{…},{…},{…},{… 수작업이나 엑셀은 현실적이지 않기 때문에 하나씩 필드로 데이터베이스에 저장해야 합니다. 그래서 이 프레임워크의 사용법을 이해하러 갔습니다.

Excel은 다음과 같습니다.

참고: Excel은 엔터티 클래스에 해당하는 매개 변수 열에서 직접 읽기 시작하므로 헤더가 없습니다.

3. 구체적인 이용절차

1. pom.xml 구성을 추가해야 합니다.

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

2. 코드에는 세 단계가 있습니다.

  1. Excel에 해당하는 엔티티 개체 Dao 클래스를 만듭니다.
  2. 쓰기 리스너: 기본적으로 엑셀을 한 줄씩 읽는 것이므로 한 줄씩 엑셀에 대한 콜백 리스너를 만들어야 합니다.리스너는 주로 읽기 및 저장을 실현합니다.
  3. 리스너 호출: Excel의 위치를 ​​구성하고 리스너를 호출하여 테이블을 읽은 다음 데이터베이스에 저장합니다.

1단계: 엑셀에 해당하는 엔터티 클래스 생성

추신 : @ExcelProperty 주석을 사용하여
여기에 이미지 설명 삽입
해당 Excel 열
"저항 테스트 데이터"에 해당하는 엔터티 클래스 를 설명합니다(여기에서 설명해야 함, 당시 Excel에서 4개의 매개 변수 이름을 모두 해당 영어 이름으로 대체했습니다).
여기에 이미지 설명 삽입
데이터베이스에 저장된 테이블 구조가 Excel에 해당하는 엔터티 클래스와 다릅니다(예를 들어 필드 읽기가 위 그림에서 Excel의 "저항 테스트 데이터"와 같은 배열 개체 구조인 경우 다음이 필요합니다. 처리하여 여러 필드로 분할하여 데이터베이스에 별도로 저장할 수 있음), 모든 데이터를 수신하여 데이터베이스에 저장하려면 데이터베이스의 테이블에 해당하는 추가 클래스를 (약간) 생성해야 합니다.

데이터베이스에서 생성한 테이블:여기에 이미지 설명 삽입

2단계: 리스너 작성

리스너 구현

/**
 * Date:2021/10/20
 * Description: excel一行一行的回调监听器
 *
 * @author ivyhu
 */
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
    
    

    @Resource
    ChargingStationMapper charingStationResistanceReportMapper;
    @Resource
    CharingStationServiceImpl charingStationServiceImpl;

    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);

    /**
     * 有参构造
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param serviceImpl
     */
    public DemoDataListener(CharingStationServiceImpl serviceImpl) {
    
    
        this.charingStationServiceImpl = serviceImpl;
    }
    //无参构造
    public DemoDataListener() {
    
    
    }
    /**
     * 读取数据或执行这个invoke()方法
     * @param excelModel 类型
     * @param context    分析器
     */
    @Override
    public void invoke(ExcelModel excelModel, AnalysisContext context) {
    
    
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(excelModel));
        //最终要保存到数据库的数据
        ChargingStationModel reportModelData = new ChargingStationModel();

        String productModelNum = "";
        String itemNo = "";
        Double groundResistance = 0.0;
        Double insulationResistance = 0.0;
        Byte type = 0;
        Integer singlePilePower = 0;
        /**
         * 获取excel表中充电设施产品信息
         */
        String str1 = excelModel.getInfoData();
        JSONArray array1 = JSON.parseArray(str1);
        //如果不为空,就解析[{},{},{},{}]类型的数组对象并获取值
        if (!ObjectUtils.isEmpty(array1)) {
    
    
            for (Object obj : array1) {
    
    
                JSONObject jsonObject = (JSONObject) obj;
                ChargingStationInfoDataExcelModel infoExcelModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationInfoDataExcelModel.class);
                type = infoExcelModel.getType();
                singlePilePower = infoExcelModel.getSinglePilePower();
            }
        }
        /**
         * 获取excel表中电阻测试数据
         */
        String str = excelModel.getResistanceData();
        JSONArray array = JSON.parseArray(str);
        //电阻测试数据不为空,就解析[{},{},{},{}]类型的数组对象并获取值
        if (!ObjectUtils.isEmpty(array)) {
    
    
            for (Object obj : array) {
    
    
                JSONObject jsonObject = (JSONObject) obj;
                ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationResistanceDataExcelModel.class);
                productModelNum = reportModel.getProductModelNum();
                itemNo = reportModel.getItemNo();
                groundResistance = reportModel.getGroundResistance();
                insulationResistance = reportModel.getInsulationResistance();
                //插入数据到数据库
                reportModelData = new ChargingStationModel(excelModel.getReportNo(), excelModel.getModelNum(), productModelNum, itemNo, groundResistance, insulationResistance, type, singlePilePower,
                        excelModel.getOutputVoltageControlErrorOfCharger(), excelModel.getOutputCurrentControlErrorOfCharger(), excelModel.getActiveStopChargeTestOutputCurrentStopRate(), excelModel.getPassiveStopChargeTestOutputCurrentStopRate(),
                        excelModel.getChargerOutputCurrentAdjustmentTimeAbove20A(), excelModel.getChargerOutputCurrentAdjustmentTimeUnder20A(), excelModel.getImpulseCurrent());
                saveData(reportModelData);
            }
        }
    }

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

        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        /*saveData();*/
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData(ChargingStationModel resistanceReportModel) {
    
    
        //调用mapper插入数据库
        charingStationServiceImpl.save(resistanceReportModel);
    }


}

3단계: 수신기를 호출하여 데이터 읽기
1. 컨트롤러 계층

@RestController
@Controller
@RequestMapping("/product/charging_station")
public class ChargingStationController {
    
    

    @Resource
    CharingStationService charingStationService;
    /**
     * 提取excel表格数据的接口
     */
    @PostMapping()
    public void saveExcel(){
    
    
        charingStationService.saveData();
    	}
    }

2. 서비스 레이어

@Service
public class CharingStationServiceImpl implements CharingStationService {
    
    

    @Resource
    ChargingStationMapper chargingStationMapper;
    @Resource
    ExcelUtil excelUtil;
    @Resource
    ChargingStationAcceptanceValueMapper chargingStationAcceptanceValueMapper;

    /**
     * 调用读取excel数据的方法
     */
    @Override
    public void saveData() {
    
    
        excelUtil.excelRead();
    }

3. 리스너 항목
엑셀에 해당하는 파일 주소, 파일명, 엔터티 클래스 설정

@Component
public class ExcelUtil {
    
    

    @Autowired
    private CharingStationServiceImpl charingStationServiceImpl;
    /**
     * 最简单的读
     * 1. 创建excel对应的实体对象 ExcelModel
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * 3. 直接读即可
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);
    
    //文件位置
    String PATH = "D:\\excelTest\\";


    public void excelRead() {
    
    

        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        String fileName = PATH + "充电桩验收测试数据.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();

    }
}

이 문서의 지식 포인트:

  1. Json을 변환하고 [{},{},{},{}] 유형 배열 객체를 구문 분석하여 내부의 단일 콘텐츠를 가져옵니다.
JSONObject jsonObject = (JSONObject) obj;
ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj);
  1. @Component 주석을 사용하여 DemoDataListener 및 리스너 항목을 Spring에 전달하여 관리
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
    
    
...
}
  1. 읽을 파일 위치 구성
//文件位置
    String PATH = "D:\\excelTest\\";

    public void excelRead() {
    
    

        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        String fileName = PATH + "充电桩验收测试数据.xlsx";

        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();

    }

추신: 작업 시작 시 몇 가지 오류가 보고되었습니다.

  1. 매퍼가 널 포인터를 보고합니다. 두 가지 가능성 중 하나는 DemoDataListener와 리스너 항목 클래스가 Spring에 주입되지 않았기 때문에 Bean을 찾을 수 없고 @Component를 사용해야 하기 때문이라는 두 가지 가능성을 확인했습니다. 두 번째는 Spring mvc의 모델 호출이 통과되지 않았지만 오픈 소스 프레임워크의 단위 테스트 @Test가 적용되어 실행된다는 것입니다.
  2. 헤더 열이 삭제되지 않아 파일 읽기에 실패했습니다.

이 글은 꼬마 신인의 작은 기록일 뿐이니, 틀린 부분이 있으면 정정 부탁드립니다!

추천

출처blog.csdn.net/Ivy_Xinxxx/article/details/121036543