处理Java EE应用程序中的大型记录

有一个表有两列的表格: idnumber 。 表中有大约half a million entries 。 数据库是MySQL

要求是开发一个连接到该数据库的简单Java EE应用程序,允许用户通过遵循特定的URL以comma separated style下载所有number值。

如果我们在一个巨大的String array获取所有值,然后在String array连接它们(在所有值之间使用逗号),然后将其发送给用户,它听起来是否合适?

该申请不公开,将由有限的号码使用。 人

最好的办法是以任何方式将数据存储在Java内存中,而是在数据进入时立即将获取的数据写入响应。还需要配置MySQL JDBC驱动程序以逐行提供结果集通过Statement#setFetchSize()按照MySQL JDBC驱动程序文档 ,否则它会将整个内容缓存在内存中。

假设你熟悉Servlets,这里有一个启动示例,它将所有这些考虑在内:

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); response.setHeader("Content-Disposition", "attachment;filename=numbers.txt"); // Force download popup. Connection connection = null; Statement statement = null; ResultSet resultSet = null; Writer writer = response.getWriter(); try { connection = database.getConnection(); statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); statement.setFetchSize(Integer.MIN_VALUE); resultSet = statement.executeQuery("SELECT number FROM phonenumbers"); while (resultSet.next()) { writer.write(resultSet.getString("number")); if (!resultSet.isLast()) { writer.write(","); } } } catch (SQLException e) { throw new ServletException("Query failed!", e); } finally { if (resultSet != null) try { resultSet.close; } catch (SQLException logOrIgnore) {} if (statement != null) try { statement.close; } catch (SQLException logOrIgnore) {} if (connection != null) try { connection.close; } catch (SQLException logOrIgnore) {} } } 

还有一点可以正确格式化CSV输出。 最简单的方法是使用现有的库来生成输出文件。

您可以为磁盘上的文件(在Web服务器上)生成输出,然后将浏览器重定向到该文件(使用cron作业或其他任何清理旧数据)或直接将结果流式传输回用户。

如果您是直接流式传输,请确保将MIME类型设置为将在用户的浏览器中触发下载的内容(例如text / csv或text /逗号分隔值)

如果使用Mysql 5.1+,我只需使用专有语法将文件转储到某处并在Servlet响应中流式传输。

 SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table; 

http://dev.mysql.com/doc/refman/5.1/en/select.html

对于这么多记录,如果您仍想使用JDBC,可以尝试以下操作:

  • 获取记录的数量,获取少量记录(使用查询限制)并写入它们
  • 如果达到块中的记录数,则会获取另一个记录,直到达到最大记录数