try中的Java准备语句,资源不起作用

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 with resources。我现在正在为所有数据库操作执行此操作。今天,我想将语句更改为PreparedStatement,以使查询更加安全。但是,当我试图在try with resources中使用一个准备好的语句时,我总是会遇到诸如“identifier expected”或“;”之类的错误或'”

我做错了什么?或者这不可能吗?这是我的代码:

    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工作是/应该分开的。当然,您也可以将所有内容都放在一个方法中。谢谢您的评论。为了避免混淆,将其添加到我的答案中。