3

有一个phonenumbers包含两列的表:idnumber。表中有约half a million entries。数据库是MySQL.

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

如果我们得到一个巨大的所有值String array,然后将它们连接起来(在所有值之间用逗号),String然后将其发送给用户,这听起来是一个正确的解决方案吗?

该应用程序不公开,将由有限的数量使用。的人。

4

3 回答 3

9

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

假设您熟悉 Servlet,下面是一个将所有这些都考虑在内的启动示例:

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) {}
    }
}
于 2010-02-02T00:45:34.613 回答
1

正确格式化 CSV 输出还有更多内容。使用现有的库(例如这个库)来生成输出文件是最简单的。

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

如果您直接进行流式传输,请确保将 MIME 类型设置为会在用户浏览器中触发下载的内容(例如 text/csv 或 text/comma-separated-values)

于 2010-02-01T23:35:51.590 回答
0

如果使用 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,可以试试下面的方法:

  • 获取记录数获取少量记录(使用查询限制)并写入它们
  • 如果你达到一个块中的记录数,你会获取另一个,直到你达到最大记录数
于 2010-02-02T00:48:00.023 回答