美文网首页
Oracle或MySQL数据库表资源导出Excel

Oracle或MySQL数据库表资源导出Excel

作者: 莫须有的呓语 | 来源:发表于2020-12-31 15:11 被阅读0次

本方案支持Oracle和MySQL
把数据库表资源导出成Excel共分几步?
3步:第一步,把表打开;第二步,一边查一边导、一边查一边导;第三步,关了那些流/连接

开玩笑的,实际上要好几步:

1.查询数据库信息、导出列名信息
2.获取jdbc连接
3.查询记录总数
4.设定页容量、起始第一页、总页数
5.组装分页查询的sql语句
6.分页查询,并写入Excel生成类里(在硬盘中缓存)
7.写入临时文件

一、前情提要

先贴出pom

 <!--        Excel报表导出  easypoi-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>3.2.0</version>
        </dependency>

数据库信息和表名由人工填入,需要时在数据库里查询
表中列信息可以用以下方法查出后存储起来
"DatabaseMetaData类是java.sql包中的类,利用它可以获取我们连接到的数据库的结构、存储等很多信息"

/**
     * 获取数据源信息
     *
     * @param driver   驱动
     * @param url      url
     * @param username username
     * @param password password
     * @return DataSource
     */
    private static DataSource getDataSource(String driver, String url, String username, String password) {
        HikariDataSource dataSource = new HikariDataSource();
        Properties props = new Properties();
        // oracle 必须配置此参数.
        props.setProperty("remarksReporting", "true");
        dataSource.setDriverClassName(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setDataSourceProperties(props);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

 /**
     * 获取到表字段所有属性
     *
     * @param driver    驱动
     * @param url       url
     * @param username  username
     * @param password  password
     * @param tableName tableName
     * @return
     */
    public static List<Metadata> buildTableMetadata(String driver, 
          String url, String username, String password, String tableName) throws SQLException {
        DataSource dataSource = getDataSource(driver, url, username, password);
        Connection conn = null;
        List<Metadata> metadataList = new ArrayList<>();
        try {
            conn = dataSource.getConnection();
            // 获取库名称
            String catalog = conn.getCatalog();

            // 获取数据库元数据
            DatabaseMetaData metaData = conn.getMetaData();

            // %表示所有.
            ResultSet resultSet = metaData.getColumns(catalog, "%", tableName, "%");

            ResultSet primaryKeyResultSet = metaData.getPrimaryKeys(catalog, metaData.getUserName().toUpperCase(), tableName);
            List<String> primaryKeyList = new ArrayList<>();
            while (primaryKeyResultSet.next()) {
                String primaryKeyColumnName = primaryKeyResultSet.getString("COLUMN_NAME");
                primaryKeyList.add(primaryKeyColumnName);
            }


            while (resultSet.next()) {
                // 字段名称
                String columnName = resultSet.getString("COLUMN_NAME");
                // 字段类型
                String columnType = resultSet.getString("TYPE_NAME");
                // 字段长度
                int columnSize = resultSet.getInt("COLUMN_SIZE");
                // 字段注释信息
                String remarks = resultSet.getString("REMARKS");
                // 字段精度:小数部分的位数
//            int digits = resultSet.getInt("DECIMAL_DIGITS");
                // 是否为空(1:可以为空,0不可以为空)
                int nullable = resultSet.getInt("NULLABLE");

                Metadata metadata = new Metadata();
                metadata.setColumnName(columnName);
                metadata.setTypeName(columnType);
                metadata.setColumnSize(columnSize);
                metadata.setRemarks(remarks);
                metadata.setNullable(nullable);

                if (primaryKeyList.contains(columnName)) {
                    // 是否主键:0:是;1不是
                    metadata.setColumnPrimaryKey(0);
                } else {
                    metadata.setColumnPrimaryKey(1);
                }
                if (!metadataList.contains(metadata)){

                    metadataList.add(metadata);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

二、正文

 /**
     * 导出数据库表信息
     * 1.查询数据库信息、导出列名信息
     * 2.获取jdbc连接
     * 3.查询记录总数
     * 4.设定页容量、起始第一页、总页数
     * 5.组装分页查询的sql语句
     * 6.分页查询,并写入Excel生成类里(在硬盘中缓存)
     * 7.写入临时文件
     *
     * @param mResource
     * @param exportPath
     * @return
     */
    private String exportExcel(RegisterResourceVO mResource, String exportPath) throws Exception {
        //获取数据库连接信息
        MDataSourceVO mDataSource = dataSourceMapper.selectDataSourceDetailById(mResource.getMDataSourceId());
        //获取要导出的列信息
        List<RegisterResTableColumnVO> registerResTableColumnList = registerTableResourceMapper.selectColumnsByRegisterResourceId(mResource.getId());
        //文件名称
        String fileName = mResource.getResourceName()+"-"+BaseUtil.createUUID() + ".xlsx";

        //获取数据库连接
        Class.forName(mDataSource.getDriver());
        java.sql.Connection sqlConnection = DriverManager.getConnection(mDataSource.getUrl(), mDataSource.getDbUser(), mDataSource.getDbPwd());
        //获取总行数
        long rowsCount = getRowsCount(mResource, sqlConnection);
        //页容量,可在表r_config_dic中修改(需要重启)
        long pageSize = Long.parseLong(SingletonConfigDic.getInstance().getMap("exportData").get("pageSize"));
        //起始第一页
        long pageNum = 1;
        long pageCount = (rowsCount - 1) / pageSize + 1;
        //生成查询用的sql
        String sqlSelect = getSqlSelect(mResource, mDataSource, registerResTableColumnList);

        //设定Excel列名
        List<ExcelExportEntity> entityList = newAddExcel(registerResTableColumnList);
        //每次查询的结果集
        List<Map<String, Object>> datas = new ArrayList<>();
        //分页查询,并写入Excel生成类里(在硬盘中缓存)
        Workbook workbook = null;
        workbook = getWorkbook(mResource, mDataSource, sqlConnection, pageSize, pageNum, pageCount, sqlSelect, entityList, datas, workbook);
        //写一个文件输出流,把内存中的excel文件写出去
        FileOutputStream fos = new FileOutputStream(exportPath + fileName);
        workbook.write(fos);
        fos.close();
        return fileName;

    }

三、高潮

    /**
     * //获取记录总数
     *
     * @param mResource
     * @param sqlConnection
     * @return
     * @throws SQLException
     */
    private long getRowsCount(RegisterResourceVO mResource, java.sql.Connection sqlConnection) throws SQLException {
        //查询计数sql
        String sqlCount = "select count(*) from " + mResource.getResourceName();
        long rowsCount = 0L;
        PreparedStatement ps = sqlConnection.prepareStatement(sqlCount);
        ResultSet rs = ps.executeQuery();
        if (rs.next()) {
            rowsCount = rs.getLong(1);
        }
        return rowsCount;
    }

    /**
     * 生成查询sql
     *
     * @param mResource
     * @param mDataSource
     * @param registerResTableColumnList
     * @return
     * @throws Exception
     */
    private String getSqlSelect(RegisterResourceVO mResource, MDataSourceVO mDataSource, List<RegisterResTableColumnVO> registerResTableColumnList) throws Exception {
        //查询sql
        String sqlSelect = "select ";
        //拼接列名
        for (RegisterResTableColumnVO column : registerResTableColumnList) {
            sqlSelect += column.getColumnName() + ",";
        }
        //mysql和oracle的区别(分页)
        switch (mDataSource.getDbType()) {
            case "1":
                //mysql
                sqlSelect = sqlSelect.substring(0, sqlSelect.length() - 1);
                sqlSelect += " from " + mResource.getResourceName() + " limit ?,?";
                break;
            case "2":
                //oracle
                sqlSelect = "select * from (" + sqlSelect + "rownum rn" + " from " + mResource.getResourceName() + " where rownum<=?) temp where temp.rn>?";
                break;
            default:
                throw new Exception("数据库类型未知|");
        }
        return sqlSelect;
    }


    /**
     * 设定导出时的列名
     *
     * @param registerResTableColumnList
     * @return
     */
    private List<ExcelExportEntity> newAddExcel(List<RegisterResTableColumnVO> registerResTableColumnList) {
        List<ExcelExportEntity> entityList = new ArrayList<>();
        for (RegisterResTableColumnVO registerResTableColumnVO : registerResTableColumnList) {
            entityList.add(new ExcelExportEntity(registerResTableColumnVO.getColumnName(), registerResTableColumnVO.getColumnName()));
        }
        return entityList;
    }
    /**
     * 分页查询,并写入Excel生成类里(在硬盘中缓存)
     *
     * @param mResource
     * @param mDataSource
     * @param sqlConnection
     * @param pageSize
     * @param pageNum
     * @param pageCount
     * @param sqlSelect
     * @param entityList
     * @param datas
     * @param workbook
     * @return
     * @throws SQLException
     */
    private Workbook getWorkbook(RegisterResourceVO mResource, MDataSourceVO mDataSource, java.sql.Connection sqlConnection, long pageSize, long pageNum, long pageCount, String sqlSelect, List<ExcelExportEntity> entityList, List<Map<String, Object>> datas, Workbook workbook) throws SQLException {
        logger.info("开始分页查询");
        while (pageNum <= pageCount) {
            logger.info("====" + pageNum + "===========");
            //分页查询数据
            PreparedStatement ps = sqlConnection.prepareStatement(sqlSelect);
            //添加参数
            ps.setLong(1, "1".equals(mDataSource.getDbType()) ? ((pageNum - 1) * pageSize) : (pageNum * pageSize));
            ps.setLong(2, "1".equals(mDataSource.getDbType()) ? pageSize : ((pageNum - 1) * pageSize));
            ResultSet rs = ps.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            //结果集存入
            while (rs.next()) {
                Map<String, Object> map = new HashMap<String, Object>();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    String colName = rsmd.getColumnName(i);
                    Object colValue = rs.getObject(i);
                    if (colValue == null) {
                        colValue = "";
                    }
                    map.put(colName, colValue);
                }
                datas.add(map);
            }

            //设定title,sheet名
            ExportParams exportParams = new ExportParams(mResource.getResourceName(), mResource.getResourceName());
            //循环分页查询数据,写入easypoi(在硬盘中缓存)
            workbook = ExcelExportUtil.exportBigExcel(exportParams, entityList, datas);
            datas.clear();
            pageNum++;
        }
        return workbook;
    }

相关文章

网友评论

      本文标题:Oracle或MySQL数据库表资源导出Excel

      本文链接:https://www.haomeiwen.com/subject/yrkmcktx.html