【问题标题】:Unable to resolve SonarQube bug for close preparedsStatement无法解决关闭 preparesStatement 的 SonarQube 错误
【发布时间】:2019-09-16 11:00:17
【问题描述】:

我有一个 JDBCStreamTemplate 类,它调用类中的另外两个方法 - JDBCStreamRow 和 JDBCStreamResultSet。这两个类实现了 Autoclosable。

JDBCStreamTemplate 类方法有connection 和preparedStatement。 sql和connection的参数通过构造函数传递给JDBCStreamRow和JDBCStreamResultSet。

连接和 PresparedStatement 正在 JDBCStreamRow 和 JDBCStreamResultSet 类中关闭。但是 SONARQube 给出的错误是 Connection 和 PreparedStatement 需要在 JDBCStreamTemplate 类中关闭。

请告诉我如何解决这个错误?

我试图通过最终放入 JDBCStreamTemplate 来关闭 PS 和 CON,但它在任何预期结果之前显示 Statement Closed。 下面的代码是调用 JdbcStreamResultSet 构造函数的 JDBCStreamTemplate 类方法

try {
Connection connection = DataSourceUtils.getConnection(this.getDataSource());
    connection.setAutoCommit(false);
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setFetchSize(5000);
    this.newArgPreparedStatementSetter(args).setValues(preparedStatement);
    jdbcStreamResultSet = new JdbcStreamResultSet(qRef, connection, preparedStatement);
} catch (SQLException sqle) {
    logger.error("{} JdbcStreamTemplate::streamResultSet: {}", qRef, JdbcUtilities.formatException(sqle));
    throw sqle;
} catch (CannotGetJdbcConnectionException ce) {
    SQLException sqle = new SQLException(ce.getMostSpecificCause());
    logger.error("{} JdbcStreamTemplate::streamResultSet: {}", qRef, Helpers.getExceptionMessage(sqle));
    throw sqle;
}

    return jdbcStreamResultSet;
}

【问题讨论】:

    标签: java jdbc sonarqube prepared-statement


    【解决方案1】:

    但是 SONARQube 给出的错误是 Connection 和 PreparedStatement 需要在 JDBCStreamTemplate 类中关闭。

    是的,打开某些东西的代码也应该是负责关闭它的代码,这是一种很好的做法!在调用树上上下拆分该职责(即在一种方法中“创建/打开”,在另一种方法中关闭)使得难以遵循控制流程,因此自找麻烦。

    连接和 PresparedStatement 在 JDBCStreamRow 和 JDBCStreamResultSet 类中被关闭。

    另一件事是我在您的代码中没有看到任何“关闭”的内容。你说 connection 和 prepareStatement 在你的其他类中被关闭,但是

    a) 你也永远不会关闭其他类,并且

    b) 我们没有这些代码,

    SO .......我将忽略您的其他类,而只是确保在此代码中关闭连接和preparedStatement。

    JDBCStreamRow 和 JDBCStreamResultSet。这两个类实现了 Autoclosable。

    connection 和preparedStatement 都实现了AutoCloseable,因此希望您能够将我将要使用的相同想法应用到您自己的类中。

    了解如何使用Autocloseable 很重要。这并不意味着 JVM 在关闭对象时会自行做出任意决定。相反,这意味着该对象在 try-with-resources 块的“资源”部分中使用时将被关闭。

    对于连接和preparedStatement,这意味着我们可以更改您的代码以使用try-with-resources:

        try ( Connection connection = DataSourceUtils.getConnection(this.getDataSource());
              PreparedStatement preparedStatement = connection.prepareStatement(sql);
            )
        { 
            connection.setAutoCommit(false);
            preparedStatement.setFetchSize(5000);
            this.newArgPreparedStatementSetter(args).setValues(preparedStatement);
            jdbcStreamResultSet = new JdbcStreamResultSet(qRef, connection, preparedStatement);
        } catch (SQLException sqle) {
            logger.error("{} JdbcStreamTemplate::streamResultSet: {}", qRef, 
                JdbcUtilities.formatException(sqle));
            throw sqle;
        } catch (CannotGetJdbcConnectionException ce) {
            SQLException sqle = new SQLException(ce.getMostSpecificCause());
            logger.error("{} JdbcStreamTemplate::streamResultSet: {}", qRef, Helpers.getExceptionMessage(sqle));
            throw sqle;
        }
    
        return jdbcStreamResultSet;
    }
    

    使用这种布局,无论发生什么事情,connection 和preparedStatement 都会保证关闭(并且顺序正确)——SONARQube 应该会很高兴。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      相关资源
      最近更新 更多