处理Java EE应用程序中的大型记录
有一个表有两列的表格: id
和number
。 表中有大约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,可以尝试以下操作:
- 获取记录的数量,获取少量记录(使用查询限制)并写入它们
- 如果达到块中的记录数,则会获取另一个记录,直到达到最大记录数