Java SQL 语句关闭

Posted

技术标签:

【中文标题】Java SQL 语句关闭【英文标题】:Java SQL Statement closing 【发布时间】:2020-04-29 16:24:56 【问题描述】:

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

启动时连接到数据库 运行 SQL 查询以创建 TABLE IF NOT EXIST (First Statement) 监听命令foo并运行foo(cmd)方法 在此方法中执行 SQL 查询 (Second Statement) 这可以重复多次 程序终止时关闭连接

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

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

我有时也会出错:

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

【问题讨论】:

您应该为每个查询创建->执行->关闭。否则你会泄露资源。你应该使用连接池。如果您想要更好的性能,请使用PreparedStatement,您可能需要调整获取大小。这不是一个可以很好地涵盖 SO 的主题。关于优化使用 sql 的应用程序的书籍有很多。 我不需要优化 :) 我只需要确认,我应该打开->执行->关闭。我不确定语句不应该处理多个查询。 【参考方案1】:

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

    连接是资源;他们必须关闭。语句(甚至是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
            
        
    

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

【讨论】:

资源究竟什么时候“关闭”?据我了解,我不需要在 conn/statement 上明确调用 .close() 您需要显式调用 close,通常在 finally 子句中。不过,正如在这个答案中一样,“使用资源尝试”会自动为您执行此操作。 @Baterka 资源在代码从此处的 try 语句的大括号中流出时关闭。没关系。所以,如果你在 try (Connection con = ...) /* code here / return 中间返回; / 这里有更多代码 */ – 在它实际返回之前,资源首先被关闭。如果代码通过异常退出块,或者仅仅因为它到达末尾,也是如此。您无需自己致电 close,它会为您处理好。

以上是关于Java SQL 语句关闭的主要内容,如果未能解决你的问题,请参考以下文章

java.sql.SQLException: SQL 语句在 org.hsqldb.jdbc.JDBCUtil.sqlException 处关闭

在java中执行多条SQL语句

从 Java 到 Oracle SQL 的翻译:将每个元素作为 SELECT 语句的结果使用到循环中[关闭]

如何使用 Java 执行多条 SQL 语句?

Mybatis_01

java之JDBC多条语句执行