try中的Java准备语句,资源不起作用
昨天,堆栈上有多人建议使用try with resources。我现在正在为所有数据库操作执行此操作。今天,我想将语句更改为PreparedStatement,以使查询更加安全。但是,当我试图在try with resources中使用一个准备好的语句时,我总是会遇到诸如“identifier expected”或“;”之类的错误或'” 我做错了什么?或者这不可能吗?这是我的代码:try中的Java准备语句,资源不起作用,java,sql,prepared-statement,Java,Sql,Prepared Statement,昨天,堆栈上有多人建议使用try with resources。我现在正在为所有数据库操作执行此操作。今天,我想将语句更改为PreparedStatement,以使查询更加安全。但是,当我试图在try with resources中使用一个准备好的语句时,我总是会遇到诸如“identifier expected”或“;”之类的错误或'” 我做错了什么?或者这不可能吗?这是我的代码: try (Connection conn = DriverManager.getConnection(DB
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1");
stmt.setInt(1, user);
ResultSet rs = stmt.executeQuery()) {
// if no record found
if(!rs.isBeforeFirst()) {
return false;
}
// if record found
else {
return true;
}
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
请尝试以下代码:
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS)) {
PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1");
stmt.setInt(1, user);
ResultSet rs = pstmt.executeQuery())
// if no record found
if(!rs.isBeforeFirst()) {
return false;
}
// if record found
else {
return true;
}
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
请注意,这里的资源是您的连接,您必须在try块中使用它
stmt.setInt(1, user);
ResultSet rs = stmt.executeQuery()
…在中尝试{/*HERE*/}
这是因为stmt
是正在创建的资源try(/*HERE*/){}
要使用try{/*HERE*/}
尝试使用资源
try (/*Create resources in here such as conn and stmt*/)
{
//Use the resources created above such as stmt
}
要点是,在资源创建块中创建的所有内容都实现了自动关闭
,当try
块退出时,close()。
在您的代码中stmt.setInt(1,用户)
不是可自动关闭的资源,因此存在问题。使用try with resource语句来声明(可自动关闭的
)资源<代码>连接
,准备语句
和结果集
都是可自动关闭的,所以这很好
但是stmt.setInt(1,user)
不是一个资源,而是一个简单的语句。在try with resource语句中不能有简单语句(没有资源声明)
解决方案:创建多个try-with-resource语句
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS)) {
executeStatement(conn);
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
private void executeStatement(Connection con) throws SQLException {
try (PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id=? LIMIT 1")) {
stmt.setInt(1, user);
try (ResultSet rs = stmt.executeQuery()) {
// process result
}
}
}
(请注意,在技术上,它不需要像我那样把SQL语句的执行放在一个单独的方法中,如果两者都打开了,打开连接并创建<代码> PravaReDebug <代码>在资源声明中的同一个尝试中。在第一行,将
;
更改为){
(愚蠢的打字?)确实,您应该在资源创建块中也包含PreparedStatement
,以便正确关闭它。好的,同意。另外,在这里找到了一篇关于同一主题的文章:可能有人可以将这篇文章标记为重复的。我还没有这个特权。但是,这篇文章没有涵盖这个特定的问题。@Ross我的意思是标记问题重复。这个问题是关于如何正确使用JDBC的try with resources,就像我发布链接的那个问题一样。此外,抛出异常时结果集不会关闭。为什么?您可以将连接
和PreparedStatement
放在同一个资源创建块中,然后使用stmt
,就是这样是的,但通常在现实世界中,打开JDBC连接和执行SQL工作是/应该分开的。当然,您也可以将所有内容都放在一个方法中。谢谢您的评论。为了避免混淆,将其添加到我的答案中。