首页 > 解决方案 > Java SQL 语句关闭

问题描述

我有一个简单的 Java 程序,它监听命令然后执行 SQL 查询。程序有以下结构:

我的问题是如何处理Statements。我应该create->execute->close为每个查询吗?或者我应该创建一个Statement并多次使用它(statement.execute();)直到我停止应用程序?

我问是因为我的 MySQL 服务器有时非常滞后,我认为这是因为我有太多未关闭的语句或池连接。

我有时也会出错:

java.sql.SQLException:语句关闭后不允许任何操作。

标签: javamysqlsql

解决方案


  1. 你应该很少使用Statement; 你几乎总是想要PreparedStatement。使用Statement意味着您不能将任何用户输入放入语句中。如果你尝试,即:statement.executeQuery("SELECT * FROM users WHERE username = '" + userInput + "'");,你刚刚写了一个安全漏洞。如果用户作为输入发送怎么办:"foo'; DROP TABLE users; EXECUTE SHELL 'rm -rf /'; --"?- 唯一的出路是逃避它,以及PreparedStatement如何做到这一点。

  2. 连接是资源;他们必须关闭。语句(甚至preparedstatements)也是如此,结果集也是如此。每个都需要被视为一种资源。

要使用资源,您可以编写如下代码:

try (Connection con = DriverManager.getConnection(...)) {
    try (PreparedStatement ps = con.prepareStatement("SELECT * FROM users WHERE username = ?")) {
        ps.setString(1, username);
        try (ResultSet rs = ps.executeQuery()) {
            while (rs.next()) {
                // handle a row worth of results here
            }
        }
    }
}

这种构造确保无论发生什么(您返回、中断、抛出异常 - 无关紧要),一旦代码移出大括号,资源就会被正确地处理掉。不这样做意味着数据库引擎会随着时间的推移变得越来越迟钝,最终您的应用程序崩溃,因为数据库停止为您提供更多连接以让您闲置。


推荐阅读