SonarQube 不断抱怨 Use try-with-resources or close this "PreparedStatement" in a "finally" clause

SonarQube keeps complaining about Use try-with-resources or close this "PreparedStatement" in a "finally" clause

我正在尝试根据用户 ID 从 table 获取电子邮件。但是,SonarQube 一直在抱怨我已经拥有的 Use try-with-resources or close this "PreparedStatement" in a "finally" clause。 我查看了答案 here 和其他地方,但这些解决方案对我不起作用。 这是代码:

public String getUserEmail(String id) throws SQLException {
        String emailAddress = null;
        String sql = "select email from my_table where id=?";
        PreparedStatement preparedStatement = this.connection.prepareStatement(sql);
        preparedStatement.setString(1, id);
        try {
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                emailAddress = rs.getString("email");
            }
        } catch(SQLException e) {
            throw new TuringClientException("Failed to getUserEmail. ", e);
        } finally {
            preparedStatement.close();
        }
        return emailAddress;
    }

我也尝试过将 PreparedStatement preparedStatement = this.connection.prepareStatement(sql) 包装在另一个 try catch 中或进行嵌套的 try-catch 但 none 的尝试有效。

你可以试试(尝试资源)

public String getUserEmail(String id) throws SQLException {
        String emailAddress = null;
        String sql = "select email from my_table where id=?";
        try(PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
            preparedStatement.setString(1, id);
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                emailAddress = rs.getString("email");
            }
        } catch(SQLException e) {
            throw new TuringClientException("Failed to getUserEmail. ", e);
        }
        return emailAddress;
    }

setString 可能会抛出一个 SQLException。如果语句准备成功,然后 setString 抛出异常,它将在 try 块的 外部 抛出异常,并且语句永远不会关闭。将 prepareStatement 移动到嵌套的 try 应该没问题,只要你在正确的 finally 块中有 clsoe (并且没有看到你做了什么很难说为什么 SonarQube 抱怨它),但老实说,使用 try-with-resource 语法会更简洁。顺便注意一下,ResultSet也要关闭:

public String getUserEmail(String id) throws SQLException {
    String emailAddress = null;
    String sql = "select email from my_table where id=?";
    try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql) {
        preparedStatement.setString(1, id);
        try (ResultSet rs = preparedStatement.executeQuery()) {
            while (rs.next()) {
                emailAddress = rs.getString("email");
            }
        } catch(SQLException e) {
            throw new TuringClientException("Failed to getUserEmail. ", e);
        }
    }
    return emailAddress;
}