1. 程式人生 > >Java POI Mysql與excel間的資料匯入匯出

Java POI Mysql與excel間的資料匯入匯出

​ 本文介紹的是利用Apache poi 的api將mysql中的資料匯出到excel表中及將excel表中的資料插入到mysql中。我封裝成了工具類,匯出的時候想匯出哪張表只需要寫sql語句就可以了。匯入到mysql的時候因為我專案中用到了mybatis有與資料庫中對應的實體類,所以匯入的時候是通過反射將excel表中的資料封裝到實體類中,再返回一個裝有實體類的集合,接著你就可以通過mybatis將list中的實體類資料插入到mysql中了。或者拿這個list隨便你幹什麼。

一、準備工作

匯入apache poi 的jar包。poi的maven座標:

<dependency>
    <
groupId
>
org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </
dependency
>

演示所用到的表:

1541926125112

二、從mysql到出到excel中。

匯出到excel的主要程式碼:

/**
 * Created by otote Cotter on 2018/11/9 9:21.
 * 自定義的poi工具類
 * 將mysal中的表匯出到excel
 * 將excel中的資料匯入到mysql
 */
public class MyPoiUtil {

    /**
     * 匯出到excel中
     * @param connection  與資料庫的連線
     * @param sql  查詢的sql語句 select * from 表名
     * @param tableName excel的sheet名
     * @param filePath  輸出的檔案路徑
     */
public static void exportToExcel(Connection connection,String sql,String tableName,String filePath){ ResultSet resultSet = null; PreparedStatement statement = null; OutputStream os=null; //建立一個excel工作簿 HSSFWorkbook workbook = new HSSFWorkbook(); //建立表 並設定sheet的名稱 HSSFSheet sheet = workbook.createSheet(tableName); //建立標題行 HSSFRow row = sheet.createRow(0); //日期格式化 HSSFCellStyle cellStyle = workbook.createCellStyle(); HSSFCreationHelper creationHelper = workbook.getCreationHelper(); cellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss")); try { //通過傳進來的sql 查詢表中的資料 statement = connection.prepareStatement(sql); //獲取結果集 resultSet = statement.executeQuery(); //獲取元資料 用來獲取欄位名 ResultSetMetaData metaData = resultSet.getMetaData(); //每一行的列數 int columnCount = metaData.getColumnCount(); //動態根據欄位名設定列名 即標題 for (int i = 0; i < columnCount; i++) { String labelName = metaData.getColumnLabel(i + 1); row.createCell(i).setCellValue(labelName); } int i=1; //臨時行 HSSFRow tempRow; //遍歷結果集 往excel中寫資料 while (resultSet.next()){ //建立臨時行 即當前行 tempRow = sheet.createRow(i); for (int j = 0; j < columnCount; j++) { //獲取當前單元格 HSSFCell tempCell = tempRow.createCell(j); //獲取資料庫中與當前格對應的資料 Object temp=resultSet.getObject(j+1); //如果獲取到的資料為空則跳過該單元格 if (temp==null || "".equals(temp)){ continue; } //如果獲取到的是時間 則格式化時間再寫到excel中 if (temp instanceof java.util.Date){ //給日期設定樣式 tempCell.setCellStyle(cellStyle); tempCell.setCellValue((java.util.Date) temp); }else if(temp instanceof Boolean){ tempCell.setCellValue((Boolean) temp); }else if (temp instanceof Double){ tempCell.setCellValue((Double) temp); }else { tempCell.setCellValue(temp.toString()); } } i++; } os=new BufferedOutputStream(new FileOutputStream(filePath)); //將excel表格寫出到指定的路徑下 workbook.write(os); System.out.println(filePath+"匯出成功"); } catch (Exception e) { e.printStackTrace(); }finally { //關閉資源 IOUtils.closeQuietly(os); if (resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } }

測試匯出:

@Test
    public void exprotTest() throws SQLException {
        //通過資料來源獲取與資料庫的連線  沒配置spring的可用原生的jdbc來獲取連線
        Connection connection = dataSource.getConnection();
        //查詢的sql語句
        String sql="select * from emp";
        //生成的excel表的路徑   注意檔名要和資料庫中表的名稱一致  因為匯入時要用到。
        String filePath="C:\\Users\\otote\\Desktop\\emp.xls";
        //匯出
        MyPoiUtil.exportToExcel(connection,sql , "emp", filePath);
    }

生成的excel表:

excel表與程式碼比較:

三、從excel表匯入到mysql中

​ 準備一個實體類。實體類的屬性名稱必須與excel表中欄位的名稱一致。因為這裡使用的是通過比較實體類的書名稱與表中的欄位名稱是否一致來將資料封裝到實體類中。如果不一致的話就需要通過自定義配置檔案將實體類的屬性名與excel中的欄位名建立對映關係了。

實體類:

public class Emp implements Serializable {
    private Integer empno;

    private String ename;

    private String job;

    private Integer mgr;

    private Date hiredate;

    private Double sal;

    private Double comm;

    private Integer deptno;

    private static final long serialVersionUID = 1L;
	//省略set、get方法
}

從excel獲取list集合

 /**
     *
     * 從excel匯入到mysql中
     * @param t 與資料庫中要插入的表對應的實體類
     * @param filePath   excel檔案的路徑
     * @param <T>
     * @return  實體類的list集合
    */
    public static <T> List<T> importToMysql(Class<T> t, String filePath){

        //準備一個list用來存放結果
        List<T> list=new ArrayList<>();

        HSSFWorkbook workbook= null;
        try {
            //通過檔案路徑建立一個工工作簿
            workbook = new HSSFWorkbook(new FileInputStream(filePath));
        } catch (IOException e) {
            System.out.println("檔案讀取失敗");
            System.out.println(e.getMessage());
        }

        //獲取當前excel的第一個sheet表格  如果有多個sheet就自行遍歷
        HSSFSheet sheet = workbook.getSheetAt(0);

        //獲取excel表的第一行   用來獲取表的欄位名
        HSSFRow tempRow = sheet.getRow(0);

        //獲取總的行數
        int lastRowNum = sheet.getLastRowNum();

        //遍歷行    從第二行開始   第一行為表的欄位名
        for (int i = 1; i <= lastRowNum; i++) {
            HSSFRow row = sheet.getRow(i);

            //獲取列數
            int cells = row.getPhysicalNumberOfCells();

            //例項化實體類物件
            T tempT= null;
            try {
                tempT = t.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            //遍歷當前行的每一列
            for (int j = 0; j < cells; j++) {
                //當前列的值
                HSSFCell hsscell = row.getCell(j);
                //當前列的名稱
                HSSFCell cellName= tempRow.getCell(j);

                Field field = null;
                try {
                    //根據列名獲取實體類與之對應的屬性
                    field = tempT.getClass().getDeclaredField(cellName.toString());
                } catch (NoSuchFieldException e) {
                    System.out.println(field.getName()+"屬性獲取失敗");
                    System.out.println(e.getMessage());
                }

                //如果該欄位為空  則跳過
                if (hsscell==null){
                    continue;
                }

                try {
                    //根據從excel獲取到的資料的型別設值
                    if (field!=null){
                        //私有屬性授權
                        field.setAccessible(true);
                        if (hsscell.getCellTypeEnum()== CellType.NUMERIC){
                            if(HSSFDateUtil.isCellDateFormatted(hsscell)){//日期
                                if (field.getType()== Date.class){
                                    field.set(tempT,hsscell.getDateCellValue());
                                }
                            }else if(field.getType()==Integer.class){
                                //int型別
                                field.set(tempT,Integer.valueOf(hsscell.getStringCellValue()));
                            }else if(field.getType()==Double.class){
                                //double型別
                                field.set(tempT,Double.parseDouble(hsscell.toString()) );
                            }
                        }else if (hsscell.getCellTypeEnum()==CellType.BOOLEAN){
                            //布林值
                            if (field.getType()==Boolean.class){
                                field.set(tempT,hsscell.getBooleanCellValue() );
                            }
                        }else if(hsscell.getCellTypeEnum()==CellType.STRING){
                            if (field.getType()==Integer.class){
                                field.set(tempT,Integer.parseInt(hsscell.toString()));
                            }else if (field.getType()==Double.class){
                                field.set(tempT,Double.valueOf(hsscell.toString()) );
                            }else if (field.getType()==String.class){
                                field.set(tempT,hsscell.toString() );
                            }
                        }
                    }
                } catch (IllegalAccessException e) {
                    System.out.println(field.getName()+"設值失敗");
                    e.printStackTrace();
                }
            }
            //新增到list集合中
            list.add(tempT);
        }
        //將封裝好的list集合返回
        return list;
    }

測試:

@Test
public void importTest(){
    //要匯入的excel檔案路徑
    String filePath="C:\\Users\\otote\\Desktop\\emp.xls";
    //獲取集合 Emp.class為該excel表對應的實體類
    List<Emp> empList = MyPoiUtil.importToMysql(Emp.class, filePath);

    //遍歷檢視結果
    for (Emp emp : empList) {
        System.out.println(emp);
    }
}

控制檯結果:

Emp [Hash = -460592568, empno=7369, ename=SMITH, job=CLERK, mgr=7902, hiredate=Wed Dec 17 00:00:00 CST 1980, sal=800.0, comm=null, deptno=20, serialVersionUID=1]
Emp [Hash = 1426257137, empno=7499, ename=ALLEN, job=SALESMAN, mgr=7698, hiredate=Fri Feb 20 00:00:00 CST 1981, sal=1600.0, comm=300.0, deptno=30, serialVersionUID=1]
Emp [Hash = 1288162093, empno=7521, ename=WARD, job=SALESMAN, mgr=7698, hiredate=Sun Feb 22 00:00:00 CST 1981, sal=1250.0, comm=500.0, deptno=30, serialVersionUID=1]
Emp [Hash = 1962304190, empno=7566, ename=JONES, job=MANAGER, mgr=7839, hiredate=Thu Apr 02 00:00:00 CST 1981, sal=2975.0, comm=null, deptno=20, serialVersionUID=1]
Emp [Hash = -657240670, empno=7654, ename=MARTIN, job=SALESMAN, mgr=7698, hiredate=Mon Sep 28 00:00:00 CST 1981, sal=1250.0, comm=1400.0, deptno=30, serialVersionUID=1]
Emp [Hash = 456906682, empno=7698, ename=BLAKE, job=MANAGER, mgr=7839, hiredate=Fri May 01 00:00:00 CST 1981, sal=2850.0, comm=0.1, deptno=30, serialVersionUID=1]
Emp [Hash = 451916084, empno=7782, ename=CLARK, job=MANAGER, mgr=7839, hiredate=Tue Jun 09 00:00:00 CST 1981, sal=2450.0, comm=null, deptno=10, serialVersionUID=1]
Emp [Hash = -1064233035, empno=7788, ename=SCOTT, job=ANALYST, mgr=7566, hiredate=Sun Apr 19 00:00:00 CDT 1987, sal=3000.0, comm=null, deptno=20, serialVersionUID=1]
Emp [Hash = 1751776396, empno=7839, ename=KING, job=PRESIDENT, mgr=null, hiredate=Tue Nov 17 00:00:00 CST 1981, sal=5000.0, comm=null, deptno=10, serialVersionUID=1]
Emp [Hash = -1419781523, empno=7876, ename=ADAMS, job=CLERK, mgr=7788, hiredate=Sat May 23 00:00: