最近遇到一个问题,就是如何将excel表格数据中几百上千行的数据导入到数据库中,使用Navicat工具的手动导入一直不成功,所以就选择使用代码的方式来进行导入,过程也比较简单,我们一起来看一下是如何实现的。
文章目录
一、准备工作
使用到的是Hutool工具库
工具介绍:
使用的是 Hutool 工具库,它是一个开源的 Java 工具库,提供了丰富的工具类和方法,可用于简化日常 Java 开发中的许多重复性繁琐任务。
Hutool 的特点在于其轻量、易用、高效和全面。它包含了各种常用的工具类,如字符串、日期、文件、加密、网络等等,还提供了一些增强型 IO 操作和线程池功能。使用 Hutool 可以大大提高编码效率,并优化开发体验。
本段代码中使用的 hutool-all 则是 Hutool 工具库的完整版本,包含了所有的工具类和方法。
1.1、新建一个Springboot+Mybatis的项目
可以参考我的另一篇博客:https://blog.youkuaiyun.com/Keep__Me/article/details/131115229?spm=1001.2014.3001.5501
1.2、导入hutool依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.10</version>
</dependency>
1.3、将需要导入数据的excel表格转换成csv格式
二、编码
2.1、ImportData
package com.example.student.pojo;
import cn.hutool.core.annotation.Alias;
import lombok.Data;
import java.time.LocalDate;
import java.util.Date;
@Data
public class ImportData {
@Alias("student_id")
private Integer studentId;
@Alias("class_id")
private Integer classId;
@Alias("student_name")
private String studentName;
@Alias("student_gender")
private String studentGender;
@Alias("student_birth")
private LocalDate studentBirth;
}
解释:
- @Alias(“student_id”) 写的是表格的表头名称,跟excel表格中要一致。
- private Integer studentId 写的是实体类属性名,自定义。
注意:
- 这里我使用的是lombok,如果没有使用,要手动加上getter setter方法;
- 还要注意的是,表格是只有一行表头,剩下的都是数据(类似于下图)。
2.2 ImportDataMapper.xml
插入语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.student.mapper.ImportDataMapper">
<insert id="insertOnly1" parameterType="ImportData">
insert into tb_student(student_id,class_id,student_name,student_gender,student_birth)
values(
#{studentId},#{classId},#{studentName},#{studentGender},#{studentBirth}
)
</insert>
</mapper>
2.3 ImportDataMapper
package com.example.student.mapper;
import com.example.student.pojo.ImportData;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public interface ImportDataMapper {
public Integer insertOnly1(ImportData importData);
}
2.4 ImportDataController
package com.example.student.controller;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.example.student.mapper.ImportDataMapper;
import com.example.student.pojo.ImportData;
import com.example.student.service.ImportDataService;
import org.apache.tomcat.util.buf.CharsetUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpSession;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.text.ParseException;
import java.util.TimeZone;
/**
* Author:wc
*/
@RestController
public class ImportDataController {
@Autowired
private ImportDataMapper importDataMapper;
@PostConstruct // Spring 容器加载完毕之后自动调用
public Integer importExcel() throws ParseException {
int count = 0;
//execl标题与Bean字段名对应
CsvReader csvReader = CsvUtil.getReader();
//指定文件读取路径跟编码格式
List<ImportData> rows = csvReader.read(ResourceUtil.getReader("D:/test/学生表4.csv", StandardCharsets.UTF_8), ImportData.class);
System.out.println("rows=="+rows);
ImportData importData = new ImportData();
for (ImportData bean : rows) {
System.out.println(bean);
importData.setStudentId(bean.getStudentId());
importData.setClassId(bean.getClassId());
importData.setStudentName(bean.getStudentName());
importData.setStudentGender(bean.getStudentGender());
importData.setStudentBirth(bean.getStudentBirth());
importDataMapper.insertOnly1(importData);
System.out.println("======================================");
}
return count;
}
}
三、问题解决:
3.1、读出来的数据都是空,且数量也不对
原因:因为我手动将excel文件的后缀改为了csv,导致文件有损坏。
解决:将excel文件另存为,然后选择文件格式 为csv
3.2、读出来的中文数据乱码
原因:文件编码格式跟读取的编码格式不一致
文件的格式(这里用的是notepad++工具进行打开,也是比较方便的):
读取的格式:
解决:将文件编码改为utf-8
如果读取excel出现问题(为空,数据不正确,或者乱码),可以从以下几个方面进行排查:
1、CSV 文件路径不正确。
请检查文件是否存在,确保它位于指定位置,并使用正确的文件扩展名。例如,如果您的文件名是 “学生表2.csv”,则应该确定文件扩展名为 “.csv”。
2、CSV 文件格式与代码读取方式不匹配。
请检查您的 CSV 文件是否以逗号分隔。如果你的文件是以其他符号(如分号)分隔数据的,则需要指定分隔符。例如,可以这样编写:
CsvReader csvReader = CsvUtil.getReader();
csvReader.setFieldDelimiter(';'); // 设置分隔符
List<ImportData> rows = csvReader.read(ResourceUtil.getReader("D:/test/学生表2.csv", StandardCharsets.UTF_8), ImportData.class);
System.out.println("rows=="+rows);
3、Java 导入的包不正确。
请确保您使用了正确的 CSV 解析器库,并在 Java 文件中正确导入了相关的包。
4、ImportData 类的字段与 CSV 文件列不匹配。
请检查 ImportData 类的字段名称和类型是否与 CSV 文件列名称和类型匹配。确保 ImportData 类中的每个字段都有一个对应的 CSV 列,并且它们类型相同。
5、CSV 文件编码不正确。
请确保您使用了正确的 CSV 文件编码。例如,如果您的文件使用 UTF-8 编码,则需要使用 “UTF-8” 编码来读取文件。您可以在 CsvUtil.getReader() 和 ResourceUtil.getReader() 方法中指定文件编码。
6、CSV 文件内容为空或格式不正确。
如果您的 CSV 文件内容为空或格式不正确,则您将无法读取数据。请确保您的 CSV 文件格式正确,并包含有效的数据。
四、附录(表格创建sql语句)
CREATE TABLE tb_student (
student_id INT PRIMARY KEY AUTO_INCREMENT,
class_id INT NOT NULL,
student_name VARCHAR(50) NOT NULL,
student_gender VARCHAR(10) NOT NULL,
student_birth DATE NOT NULL,
FOREIGN KEY (class_id) REFERENCES tb_class(class_id)
);