java Spring easyexcel导入到数据库Instant日期转换问题

在使用easyexcel进行导入时,遇到各种问题,下面进行总结归纳。
导入阿里巴巴EasyExcelmaven依赖

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

新建POJO类,然后找到需要转换的字段,在类上添加EasyExcel的注解@ExcelPropertyvalue对应excel的列名,index对应excel的列号(从0开始)。

@AllArgsConstructor
@NoArgsConstructor //必须要保证无参构造方法存在,否则会报初始化对象失败
@Data
public class InspectionTablePOJO {

        @ExcelProperty(value = "表名称", index = 0)
        @NotNull
        private String inspectionTableName;

        @ExcelProperty(value = "设备类型编号", index = 1)
        @NotNull
        private String equipmentTypeId;

        @ExcelProperty(value = "表建立时间", index = 2,converter = InstantConverter.class)
        @NotNull
        // @LocalDateTimeFormat} 注解 ,作用: 与 // {@code  @ExcelProperty(converter = LocalDateTimeExcelConverter.class)} 搭配使用,
        //         指定导入导出的时间格式.
        @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") 

        private Instant tableCreationTime;
    }

这里如果直接导入,由于excel的日期是字符串或者其他格式,不能转化为Instant类,会报异常,参考文章,需要指定Converter, 即自定义转换器,因为我们要转换Instant,所以编写如下转换器!注意要实现的是com.alibaba.excel.converters.Converter接口,定义完后在ExcelProperty中指定converter
InstantConverter代码如下:

public class InstantConverter implements Converter<Instant> {

        @Override
        public Class<Instant> supportJavaTypeKey() {
            return Instant.class;
        }

		// excel中日期指定为文本格式,因此指定为STRING,如果为其他格式则需要指定为其他格式
        @Override
        public CellDataTypeEnum supportExcelTypeKey() {
            return CellDataTypeEnum.STRING;
        }

        @Override
        public Instant convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
                                         GlobalConfiguration globalConfiguration) throws ParseException {

             // 将字符串转换为Instant
            Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(cellData.getStringValue());
            return date.toInstant();
        }

        @Override
        public CellData<String> convertToExcelData(Instant value, ExcelContentProperty contentProperty,
                                                   GlobalConfiguration globalConfiguration) {
            // 将Instant转换为字符串
            String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(value);
            return new CellData(out);
        }

    }

写入excel sheet中时,转换为指定格式(value)的字符串;
excel sheet中读取value格式的字符串,转换为对应的数字类型
Service层代码如下:

import static com.fii.amms.exception.ErrorEnum.FAILED_TO_ADD;
@Service
@Slf4j
public class BatchImportService{
    @Autowired
    InspectionTableMapper inspectionTableMapper;
    @Autowired
    InspectionTableConverter inspectionTableConverter;
    @Autowired
    InspectionTableExcelConverter inspectionTableExcelConverter;


    public int importInspectionTableExcel(MultipartFile file) throws AMMSException{
        ExcelUtil excelUtil = new ExcelUtil();
        try{
            excelUtil.simpleImportInspectionTable(file, inspectionTableMapper, inspectionTableConverter, inspectionTableExcelConverter);
        }catch(Exception e){
            e.printStackTrace();
            throw new AMMSException(FAILED_TO_ADD.getCode(),"导入表失败",FAILED_TO_ADD.getMsg());表名称", index = 0)
        @NotNull
        }
        return 1;
    }
}
public class ExcelUtil {
    public void simpleImportInspectionTable(MultipartFile file, InspectionTableMapper inspectionTableMapper, InspectionTableConverter inspectionTableConverter, InspectionTableExcelConverter inspectionTableExcelConverter){
        String fileName = file.getOriginalFilename();

        File dest = new File(new File("/").getAbsolutePath()+"/home/2020/"+fileName);
        System.out.println(dest.toString());
        if(!dest.getParentFile().exists()){
            dest.getParentFile().mkdirs();
        }

        try{
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        } catch(IllegalStateException ie){
            ie.printStackTrace();
        }
		
		//  这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(dest, InspectionTablePOJO.class, new InspectionTableExcelListener(inspectionTableMapper, inspectionTableConverter, inspectionTableExcelConverter)).sheet().doRead();

    }
}

编写阅读监听类,Excel文件的读操作,是通过此监听类实现的,EasyExcel是一行一行的读取文件,所以要把每一次读取的数据保存到数据库中,为了避免重复,保存之前会判断是否存在相同的数据。

//  由于在实际中可能会根据不同的业务场景需要的读取到的不同的excel表的数据进行不同操作,
// 所以这里将ExcelListener作为所有listener的基类,根据读取不同的java模型自定义一个listener类继承ExcelListener,
// 根据不同的业务场景选择性对以下方法进行重写,具体如com.luwei.listener.OrderListener所示


// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Component
public class InspectionTableExcelListener extends AnalysisEventListener<InspectionTablePOJO> {

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

    private static final int BATCH_COUNT = 5;

     // 自定义用于暂时存储data。
     // 可以通过实例获取该值
     // 可以指定AnalysisEventListener的泛型来确定List的存储类型
    List<InspectionTablePOJO> list = new ArrayList<>();

    private InspectionTableMapper inspectionTableMapper;
    private InspectionTableConverter inspectionTableConverter;
    private InspectionTableExcelConverter inspectionTableExcelConverter;

    public InspectionTableExcelListener(InspectionTableMapper inspectionTableMapper, InspectionTableConverter inspectionTableConverter, InspectionTableExcelConverter inspectionTableExcelConverter){
        this.inspectionTableMapper = inspectionTableMapper;
        this.inspectionTableConverter = inspectionTableConverter;
        this.inspectionTableExcelConverter = inspectionTableExcelConverter;
    }
     // 每隔N条存执行一次saveData()方法,
     //  如果是入库操作,可使用默认的3000条,然后清理list,方便内存回收
     // 每解析一行会回调invoke()方法。
     // 如果当前行无数据,该方法不会执行,
     // 也就是说如果导入的的excel表无数据,该方法不会执行,
     // 不需要对上传的Excel表进行数据非空判断
     // @param object  当前读取到的行数据对应的java模型对象
     // @param context 定义了获取读取excel相关属性的方法
    @Override
    public void invoke(InspectionTablePOJO inspectionTablePOJO, AnalysisContext analysisContext){
        System.out.println(inspectionTablePOJO.getInspectionTableName());
        System.out.println(inspectionTablePOJO.toString());
        list.add(inspectionTablePOJO);
        if(list.size()>=BATCH_COUNT){
            saveData();
            list.clear();
        }
    }

     // 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则继续读取下一行。
     // 如果不重写该方法,默认抛出异常,停止读取
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
        // 如果是某一个单元格的转换异常 能获取到具体行号
        // 如果要获取头的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex());
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext){
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
JAVA简单快速的读写Excel之EasyExcel
    private void saveData(){
        for(InspectionTablePOJO inspectionTablePOJO:list){

        try{
            InspectionTableDTO inspectionTableDTO = inspectionTableExcelConverter.toDTO(inspectionTablePOJO);
            InspectionTableDO inspectionTableDO = inspectionTableConverter.toDO(inspectionTableDTO);
            this.inspectionTableMapper.addInspectionTable(inspectionTableDO);
        }catch(Exception e){
            e.printStackTrace();
        }
        LOGGER.info("{}条数据,开始存储数据库!",list.size());
        LOGGER.info("存储数据库成功!");
        }
    }
}

参考文献:
Java EasyExcel读取Excel数据转换等异常处理示例代码
POI和EasyExcel-你还在为导入导出数据苦恼吗?
简单的Excel导入(上传、解析、持久化)
java日期互转:LocalDateTime、String、TimeStamp、Long、Instant、Date
使用EasyExcel上传Excel文件,并把数据保存到数据库中
为easyexcel设置TimeZone
重点easyexcel-utils
将字符串转换为Instant
将Instant格式化为String
EasyExcel自定义Converter解决LocalDateTime日期转换的问题
EasyExcel读取Excel日期为数字如何解决
重点还没看EasyExcel实现Excel文件的导入导出
EASYEXCEL自定义CONVERTER解决性别转换问题
JAVA简单快速的读写Excel之EasyExcel
EasyExcel 轻松灵活读取Excel内容
EasyExcel ----- 实现数据库数据 导出为Excel表和Excel表导入数据功能
MultipartFile 类

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值