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

发布于 2024-08-20 02:17:54 字数 368 浏览 9 评论 0原文

有一个表phonenumbers,其中包含两列:idnumber。表中大约有五十万个条目。数据库是MySQL

要求是开发一个连接到该数据库的简单 Java EE 应用程序,允许用户通过遵循特定 URL 以逗号分隔样式下载所有数字值。

如果我们获取一个巨大的字符串数组中的所有值,然后将它们连接在一个字符串中(所有值之间用逗号),然后将其发送给用户,这听起来是一个正确的解决方案吗?

该应用程序不是公开的,并且将由有限的用户使用。的人。

There is a table phonenumbers with two columns: id, and number. There are about half a million entries in the table. Database is MySQL.

The requirement is to develop a simple Java EE application, connected to that database, that allows a user to download all numbervalues in comma separated style by following a specific URL.

If we get all the values in a huge String array and then concatenate them (with comma in between all the values) in a String and then send it down to the user, does it sound a proper solution?

The application is not public and will be used by a limited no. of people.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情绪少女 2024-08-27 02:17:54

最好的办法是以任何方式将数据存储在 Java 内存中,而是在数据传入时立即将获取的数据写入响应。您还需要配置 MySQL JDBC 驱动程序以通过 Statement#setFetchSize() 根据 MySQL JDBC 驱动程序文档,否则它将把整个内容缓存在内存中。

假设您熟悉 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) {}
    }
}

Your best bet is to not store the data in Java's memory in any way, but just write the obtained data to the response immediately as the data comes in. You also need to configure the MySQL JDBC driver to serve the resultset row-by-row by Statement#setFetchSize() as per the MySQL JDBC driver documentation, otherwise it will cache the whole thing in memory.

Assuming you're familiar with Servlets, here's a kickoff example which takes that all into account:

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) {}
    }
}
月寒剑心 2024-08-27 02:17:54

正确设置 CSV 输出格式还需要更多的工作。最简单的方法是使用现有的库(例如 这个库)来生成输出文件。

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

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

There's a bit more to properly formatting CSV output. It would be easiest to use an existing library such as this one to generate the output file.

You can generate output to a file on disk (on the web server) and then redirect the browser to that file (with a cron job or whatever to clean up old data) or just stream the result directly back to the user.

If you are streaming directly be sure and set the MIME type to something that will trigger a download in the user's browser (e.g. text/csv or text/comma-separated-values)

花开雨落又逢春i 2024-08-27 02:17:54

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

  • fetch the number ofrecords fetch Few
    记录(使用查询
    limit )并
  • 在达到数量时 写下它们
    记录在一个块中,你获取另一个
    1 直到达到最大值
    记录数

If using Mysql 5.1+, I would simply use the proprietary syntax to dump the file somewhere and stream it in a Servlet response.

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

For so many records, if you still want to use JDBC, you may try the following:

  • fetch the number of records fetch few
    records( using a query
    limit ) and write them
  • if you reach the number of
    records in a chunk, you fetch another
    one until you reach the maximum
    number of records
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文