在 Java 7 中正确应用 Try with Resources?

Apply Try with Resources correctly in Java 7?

我正在使用 Angular 和 Spring 以及 Java 7 开发一个应用程序,但是,我被要求使用 SonarQube 扫描我的代码,所以这个工具告诉我我需要尝试使用资源来关闭我的 Prepared StatementResult Set,所以我做了一些研究并像这样实现它:

try (Connection connection = DriverManager.getConnection(connectionUrl);
            Statement statement = connection.createStatement();
            PreparedStatement sentence = connection.prepareStatement(selectSql);
            ResultSet resultSet = sentence.executeQuery();) {
    

        // Create and execute a SELECT SQL statement.
        sentence.setString(1, parametro);
        logger.info(resultSet + " resultSet!----------------------------------------");

        // Print results from select statement
        while (resultSet.next()) {
            logger.info(" Entro al While!----------------------------------------");
            euroList.add(new EuroModel(resultSet.getInt("ID"), resultSet.getString("RFC"),
                    resultSet.getString("NOM")));
            logger.info("recibiendo result-> " + resultSet.getString(2) + " " + resultSet.getString(3));
            logger.info(euroList.toString());

        }

    } catch (SQLException e) {
        logger.info("No se pudo conectar");
        logger.info("EuroService");
        logger.info("INFO: " + e);
        List<EuroModel> empty = null;
        return empty;
    }

但是,由于以下行在错误的位置,我的代码无法正常工作,我不知道应该在哪里尝试使用资源:

sentence.setString(1, parametro);

有人可以帮我吗?

您在设置 PreparedStatement 的参数之前正在执行查询。

您可以从 try-with-resources 中删除 ResultSet,因为 it will be closed automatically:

A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.

你想确保执行你的PreparedStatement的查询,并获得相应的ResultSet,在你设置你的参数后:

try (Connection connection = DriverManager.getConnection(connectionUrl);
        Statement statement = connection.createStatement();
        PreparedStatement sentence = connection.prepareStatement(selectSql)) {


    // Create and execute a SELECT SQL statement.
    sentence.setString(1, parametro);
    ResultSet resultSet = sentence.executeQuery();
    logger.info(resultSet + " resultSet!----------------------------------------");

更新

从中吸取的一个有用的额外教训:SonarQube 在良好的编程实践方面并不是权威。事实上,SonarQube 在半定期的基础上是错误的。

就是这种情况。 Sonar 不够聪明,无法知道 ResultSet 会在其父 Statement 关闭时自动关闭。 Sonar 只知道有一个可关闭的对象,在代码中似乎没有明确关闭。

正如 Slaw 所建议的,您可以通过为 ResultSet 使用另一个 try-with-resources 让 Sonar 满意:

try (Connection connection = DriverManager.getConnection(connectionUrl);
        Statement statement = connection.createStatement();
        PreparedStatement sentence = connection.prepareStatement(selectSql)) {


    // Create and execute a SELECT SQL statement.
    sentence.setString(1, parametro);
    try (ResultSet resultSet = sentence.executeQuery()) {
        logger.info(resultSet + " resultSet!----------------------------------------");

        while (resultSet.next()) {
            // etc.
        }
    }