SpringBoot整合SpringBoot-POI:将excel导入到mysql中

POI:  Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档r的功能。

poi的相关api也挺多的,这里介绍怎么将Excel导入Mysql

场景:需要将一个用户信息的excel表格导入到msql中的user表中,采用poi自动导入。

思想:

  • 将excel表格数据的每一行读出
  • 读取一行中的每一列,用来构建实体类
  • 将实体类添加的集合中去
  • 依次保存到数据库中

第一步:在pom文件中配置poi的依赖

      <!-- excel 导入 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>

第二步骤:添加与数据库关联的实体类

package com.whut.entity;

import javax.persistence.*;

@Entity
@Table(name = "test_users")//映射数据库表名
public class TestUser {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增生成策略
    @Column(name = "id")
    private Integer id;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @Column(name = "phone")
    private String phone;

    @Column(name = "sex")
    private String sex;

    public TestUser() {
    }


    public TestUser(String username, String password, String phone, String sex) {
        this.username = username;
        this.password = password;
        this.phone = phone;
        this.sex = sex;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "TestUser{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", phone='" + phone + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

第三步:编写Jpa接口来保存到数据库

package com.whut.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.whut.entity.TestUser;

public interface TestUserRepository extends JpaRepository<TestUser,Integer> {

}

第四步:编写service层(重点层)

package com.whut.service;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import com.whut.entity.TestUser;
import com.whut.repository.TestUserRepository;
import com.whut.utils.ExcelImportUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ExcelServiceImp implements ExcelService{

    @Autowired
    private TestUserRepository testUserRepository;

    private static final String TGA = "ExcelService : ";

    private String result = "";//返回的结果

    private String errorMsg = "";//记录错误信息


    private int getTotalRows(Workbook wb) {
        //获取第一个sheet的所有行数
        return wb.getSheetAt(0).getPhysicalNumberOfRows();
    }

    private Sheet getSheet(Workbook wb) {
        //将第一个sheet返回回去
        return wb.getSheetAt(0);
    }

    private int getTotalCell(Workbook wb) {
        Sheet sheet = getSheet(wb);

        int tempTotalRows = getTotalRows(wb);

        //得到Excel的列数(前提是有行数),从第二行算起
        //这个可以自定义,从真实数据的一行开始读取
        if (tempTotalRows >= 2 && sheet.getRow(1) != null) {
            return sheet.getRow(1).getPhysicalNumberOfCells();
        }
        return -1;
    }

    /**
     * 分批处理导入
     * @param fileName
     * @param mfile
     * @param userName
     * @param tableName 要导入得数据库表名
     * @return
     */
    public String batchImport(String fileName, MultipartFile mfile, String userName, String tableName) {


        File uploadDir = new File("E:\\fileupload");
        //创建一个目录 (它的路径名由当前 File 对象指定,包括任一必须的父路径。)
        if (!uploadDir.exists()) uploadDir.mkdirs();
        //新建一个文件
        File tempFile = new File("E:\\fileupload\\" + new Date().getTime() + ".xlsx");
        //初始化输入流
        InputStream is = null;
        try {
            //将上传的文件写入新建的文件中
            mfile.transferTo(tempFile);

            //根据新建的文件实例化输入流
            is = new FileInputStream(tempFile);

            //根据版本选择创建Workbook的方式
            Workbook wb = null;
            //根据文件名判断文件是2003版本还是2007版本
            if (ExcelImportUtils.isExcel2007(fileName)) {
                wb = new XSSFWorkbook(is);
            } else {
                wb = new HSSFWorkbook(is);
            }
            //根据excel里面的内容读取知识库信息
            return readExcel(tableName, wb, userName, tempFile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    is = null;
                    e.printStackTrace();
                }
            }
        }
        return "导入出错!请检查数据格式!";


    }//batchImport

    /**
     *
     * 返回对应表的读取实列
     *
     * 根据表名来确定要上传到得数据库
     * @param tableName 要上传到数据库的表名
     * @param wb
     * @param userName
     * @param file
     * @return
     */
    private String readExcel(String tableName, Workbook wb, String userName, File file) {

        switch (tableName) {
            case "test_users":
                return readTestUserExcelValue(wb, userName, file);
//            case "db_research_group2":
//                return readResearchGroup2ExcelValue(wb, userName, file);
//            case "db_research_group3":
//                return readResearchGroup3ExcelValue(wb,userName,file);
//            case "db_research_group4":
//                return readResearchGroup4ExcelValue(wb,userName,file);
//            case "db_research_group5":
//                return readResearchGroup5ExcelValue(wb,userName,file);
//            case "db_research_group7":
//                return readResearchGroup7ExcelValue(wb,userName,file);
//            case "db_research_group8":
//                return readResearchGroup8ExcelValue(wb,userName,file);
        }
        return null;
    }

    /**
     *
     * @param wb
     * @param userName
     * @param tempFile 临时文件,在文件读入msql后执行删除操作
     *
     * 思路:将excel表格一行行读出,
     *        循环其中得每一行,再一列列得读取出其中得每一个cell
     *         将其保存到实体类中
     *         一次保存到数据库中
     * @return
     */
    private String readTestUserExcelValue(Workbook wb, String userName, File tempFile){

        //得到第一个sheet
        Sheet sheet = getSheet(wb);
        //得到Excel的行数
        int totalRows = getTotalRows(wb);
        //总列数
        int totalCells = getTotalCell(wb);
        //得到Excel的列数(前提是有行数),从第二行算起

        List<TestUser> testUsers = new ArrayList<>();
        TestUser testUser;

        String br = "<br/>";
        //循环excel中的每一行数据
        for(int r = 1;r<totalRows;r++){
            String rowMessage = "";
            Row row = sheet.getRow(r);
            if (row == null) {
                errorMsg += br + "第" + (r + 1) + "行数据有问题,请仔细检查!";
                continue;
            }

            testUser = new TestUser();


            //循环excel中的每一列数据
            for(int c=0;c<totalCells;c++){
                //获取每一列的一个单元格
                Cell cell = row.getCell(c);//获取每一个单元格cell

                if(cell != null){
                    switch (c){
                        case 0:
                            //设置读取的字段为字符类型
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            testUser.setUsername(cell.getStringCellValue());//读取并设置到实体类中
                            break;
                        case 1:
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            testUser.setPassword(cell.getStringCellValue());
                            break;
                        case 2:
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            testUser.setPhone(cell.getStringCellValue());
                            break;
                        case 3:
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            testUser.setSex(cell.getStringCellValue());
                            break;
                    }//end switch
                }//end if

            }//end for遍历完每一列数据

            //拼接每行的错误提示
            if (!StringUtils.isEmpty(rowMessage)) {

                errorMsg += br + "第" + (r + 1) + "行," + rowMessage;
                System.out.println(TGA+errorMsg);

            } else {
                //数据正常将其添加到集合中
                testUsers.add(testUser);
            }//end if

        }//遍历完每一行数据

        //删除上传的临时文件
        if (tempFile.exists()) {
            tempFile.delete();
        }

        //将数据导入到Mysql中
        for(TestUser t:testUsers){
            this.testUserRepository.save(t);
        }

        result = "导入成功,共" + testUsers.size() + "条数据!";

        return result;
    }

}

第五步:编写工具类Utils

package com.whut.utils;

/**
 * excel导入mysql的工具
 *
 * @author zm
 */
public class ExcelImportUtils {

    public static boolean isExcel2003(String filePath) {
        return filePath.matches("^.+\\.(?i)(xls)$");
    }

    //@描述:是否是2007的excel,返回true是2007
    public static boolean isExcel2007(String filePath) {
        return filePath.matches("^.+\\.(?i)(xlsx)$");
    }

    /**
     * 验证EXCEL文件
     *
     * @param filePath
     * @return
     */
    public static boolean validateExcel(String filePath) {
        if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
            return false;
        }
        return true;
    }

}

第六步:编写controller层(访问层)

package com.whut.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.multipart.MultipartFile;
import com.whut.Model.BaseModel;
import com.whut.contant.Constant;
import com.whut.service.ExcelServiceImp;
import com.whut.utils.ExcelImportUtils;

@CrossOrigin(origins = "*")//开启跨域
@Controller
@RequestMapping("/excelImportToMysql")
public class ExcelController {

    @Autowired
    private ExcelServiceImp excelServiceImp;

    private static final String TGA = "ExcelController : ";


    @RequestMapping("/batchImportExcel")
    @ResponseBody
    public BaseModel batchImportExcel(
            @RequestParam(value = "filename") MultipartFile file,
            @RequestParam(value = "tableName") String tableName
    ) {


        System.out.println("batchImportExcel");

        if (file == null) {
            return new BaseModel(
                    Constant.ERROR,
                    "文件不能为空",
                    null
            );
        }

        String fileName = file.getOriginalFilename();

        //验证文件名是否合格
        if (!ExcelImportUtils.validateExcel(fileName)) {
            return new BaseModel(
                    Constant.ERROR,
                    "文件必须是excel格式",
                    null
            );
        }

        //进一步判断文件内容是否为空(即判断其大小是否为0或其名称是否为null)
        long size = file.getSize();

        if (StringUtils.isEmpty(fileName) || size == 0) {
            return new BaseModel(
                    Constant.ERROR,
                    "文件内容不能为空不能为空",
                    TGA
            );
        }

        String result = excelServiceImp.batchImport(fileName, file, "admin", tableName);

        return new BaseModel(
                Constant.SUCCESS,
                "导入成功:  "+result,
                null
        );

    }


}

注:

BaseModel是用来封装返回数据

package com.whut.Model;

public class BaseModel {
    //状态代码 方便前端匹配错误码表
    public int code;

    //可读性错误信息
    public String msg;

    public Object data;

    public BaseModel(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public BaseModel(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public BaseModel() {
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "BaseModel{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
}

第七步:测试编写得接口

1.使用PostMan来请求

2.检查控制台日志:

 

3.检查数据库:

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值