在try-with-resources中Java编写的语句不起作用

时间:2014-07-24 11:20:03

标签: java sql prepared-statement

昨天Stack上的多个人建议使用try-with-resources。我正在为我的所有数据库操作执行此操作。今天我想将Statement更改为PreparedStatement以使查询更安全。但是,当我尝试在try-with-resources中使用预准备语句时,我不断收到“标识符预期”或“;”等错误或')'。

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

    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;

    }

3 个答案:

答案 0 :(得分:8)

try-with-resource语句用于声明(Autoclosable)资源。 ConnectionPreparedStatementResultSetAutoclosable,这样就可以了。

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语句的执行放入单独的方法中。如果打开连接和创建PreparedStatement两者都在同一个尝试中,它也可以工作-with-resource statement。我认为将连接管理内容与其余代码分开是一种很好的做法。

答案 1 :(得分:1)

试试这段代码:

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;

    }

请注意,此处资源是您的Connection,您必须在try块中使用它()

答案 2 :(得分:1)

移动

stmt.setInt(1, user);
ResultSet rs = stmt.executeQuery()

...在try{ /*HERE*/ }

这是因为stmt是要使用的资源try (/*HERE*/) {} try{ /*HERE*/ }

<强>尝试与 - 资源

try (/*Create resources in here such as conn and stmt*/)
{
  //Use the resources created above such as stmt
}

关键是在资源创建块implements AutoClosable中创建的所有内容以及退出try块时,都会调用close()。 在您的代码中,stmt.setInt(1, user);不是AutoCloseable资源,因此存在问题。