【问题标题】:Writing a large resultset to an .xlsx file using Apache POI and JDBC使用 Apache POI 和 JDBC 将大型结果集写入 .xlsx 文件
【发布时间】:2018-05-19 22:06:22
【问题描述】:

我正在尝试将大型(总行数最多为 200 万)结果集写入 .xlsx 文件。 为了克服堆空间或内存错误,我决定在每次调用中从表中获取一些有限的记录集并将其附加到文件中。 那些有限的记录集都是按rownum排序的。在每次调用表时,我都会获取 50K 记录,最后是从表中获取所有记录并将其附加到 .xlsx 文件中。 目前我只在每张表中放入 600000 条记录。而我目前的逻辑如下。

但以下逻辑需要大量时间来创建 .xlsx 文件。有什么办法可以减少时间吗?? 创建第二张工作表后它也会失败。

    String query="select count(*) from employee";
    String actquery="";
    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    conn = DriverManager.getConnection(jdbcURL,user,passwd);
    stmt = conn.createStatement();
    rs = stmt.executeQuery(query);
    stmt.setFetchSize(1000);
    int rowcounter;
    int increaseCount=50000;
    int jdbclimit=50000;//jdbc
    int excelrowlimit=600000;
    int excellimit=600000;
    int rownumStartCnt=0;
    int rownumEndCnt=0;
    if(rs.next()){
    outStream = new FileOutputStream("D:\\Test.xlsx",true);
    int count=rs.getInt(1);

    System.out.println("Total records"+count);
    if(count>0)
    {
    int sheets= count/excelrowlimit;
    if(count%excelrowlimit>0){
           sheets = sheets+1;
    }
    for(int scount=1;scount<=sheets;scount++){
    sheet =  workbook.createSheet("GapHistory-"+scount);
    rowcounter=1;
    System.out.println("Sheet:"+scount);
    System.out.println("limit is "+jdbclimit);
    while(rowcounter<excelrowlimit)
    {
    rownumStartCnt=rownumEndCnt+1;
    rownumEndCnt=jdbclimit;
    jdbclimit=jdbclimit+increaseCount;
    if(rownumEndCnt>excellimit){
           rownumEndCnt=excellimit;
    }
    if(rownumStartCnt>count){
     break;
    }
    PreparedStatement stmt2 = null;
    ResultSet rs2 =null;
    ResultSetMetaData rsmd=null;              

    actquery=actquery+"SELECT * FROM (SELECT t.*, ROW_NUMBER() OVER (ORDER BY employee_number) rnum  FROM employee t) WHERE rnum BETWEEN ? and ?";
    stmt2 = conn.prepareStatement(actquery);
    stmt2.setInt(1,rownumStartCnt);
    stmt2.setInt(2,rownumEndCnt);
    rs2 = stmt2.executeQuery();
    System.out.println("Start row-->"+rownumStartCnt+"End row--->"+rownumEndCnt);
    rsmd = rs2.getMetaData();
    stmt2.setFetchSize(1000);
    rs2.setFetchDirection(ResultSet.FETCH_FORWARD);
    while(rs2.next())
    {

    if(rowcounter==1)
    {
           row = sheet.createRow(rowcounter);
           for(int i=1;i<=68;i++)
           {
            cell = row.createCell(i);
            cell.setCellValue(rsmd.getColumnName(i));                                                                                                                                         

           }

    }
    rowcounter++;

    for(int i=1;i<=68;i++)
    {
           if(i==1)
           {
           row = sheet.createRow(rowcounter);
           }

           cell = row.createCell(i);
           cell.setCellValue(rs2.getString(i));

    }
    }
    actquery="";

                        }
 excellimit = excellimit+excelrowlimit;// Got rid with exception after adding this line
                        }
          }
    }

【问题讨论】:

  • 请正确格式化您的代码。你在向陌生人寻求帮助,至少你能做的就是让你的代码可读。

标签: java oracle jakarta-ee apache-poi fileoutputstream


【解决方案1】:
java.sql.SQLException: ORA-01000: maximum open cursors exceeded

这意味着您打开了许多ResultSets 而没有关闭其中任何一个。最终,您会耗尽驱动程序资源。完成后,您必须关闭每个 ResultSet

顺便说一句,XLSX 的最大行数为 2^20,即 1,048,576。您不能在 XLSX 工作表中存储 200 万行。

【讨论】:

  • 感谢您的回复。是的,我知道 xlsx 的限制。这就是我在获得大于 600000 的记录时创建新工作表的原因。基本上我试图在每个 Excel 工作表中只放入 600000 条记录。更多的错误是由于没有正确遵循的逻辑。看看输出日志就知道了。
  • 我现在已经删除了异常。但需要帮助以最大限度地减少生成 .xlsx 文件的时间。
  • edit您的帖子并(1)正确格式化代码; (2) 更新叙述以反映当前情况,即删除有关异常的部分。
  • 用必要的 cmets 编辑了帖子。现在我想减少创建excel的时间。请指导我。是否有任何选项可以在从结果集中获取第一组记录后立即写入文件,而不是立即写入文件。
猜你喜欢
  • 2011-11-08
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-17
相关资源
最近更新 更多