java - Java SQL 语句关闭
问题描述
我有一个简单的 Java 程序,它监听命令然后执行 SQL 查询。程序有以下结构:
- 在启动时连接到数据库
- 运行 SQL 查询以创建 TABLE IF NOT EXIST (
First Statement
) - 监听命令
foo
和运行foo(cmd)
方法- 在该方法内执行 SQL 查询 (
Second Statement
) - 这可以重复多次
- 在该方法内执行 SQL 查询 (
- 程序终止时关闭连接
我的问题是如何处理Statements
。我应该create->execute->close
为每个查询吗?或者我应该创建一个Statement
并多次使用它(statement.execute();
)直到我停止应用程序?
我问是因为我的 MySQL 服务器有时非常滞后,我认为这是因为我有太多未关闭的语句或池连接。
我有时也会出错:
java.sql.SQLException:语句关闭后不允许任何操作。
解决方案
你应该很少使用
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
}
}
}
}
这种构造确保无论发生什么(您返回、中断、抛出异常 - 无关紧要),一旦代码移出大括号,资源就会被正确地处理掉。不这样做意味着数据库引擎会随着时间的推移变得越来越迟钝,最终您的应用程序崩溃,因为数据库停止为您提供更多连接以让您闲置。
推荐阅读
- c# - C# - 为什么在播放 2 个声音时我的表单最小化?
- javascript - 如何在用户定义的所有路由之后在 NodeJS 中添加错误处理程序?
- vega-lite - 即使聚合函数是非总结性的,也会创建堆积条形图
- python - 基于ubuntu的docker容器中的python argparse
- c++ - C++ 宏包装一个外部函数并将其添加到一个类中
- node.js - 使用 AWS SES 发送群组电子邮件
- reactjs - 字体真棒图标不可点击(反应)
- python - 为什么尝试使用 matplotlib 绘制时间是 00:00?
- c# - 无法加载文件或程序集 'Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 或其依赖项之一
- android-studio - Flutter 未检测到 Android Studio