0

我有以下代码:

try (Connection connection = getConnection();

    PreparedStatement preparedStatement = connection.prepareStatement(someSql)) {//stuff}

如何在这里检查连接不为空?

另外,我得到了一个返回 PreparedStatement 的方法,如下所示:

private PreparedStatement getPreparedStatement(Connection connection)

  throws SQLException {

PreparedStatement preparedStatement = connection.prepareStatement(SQL);

preparedStatement.setString(1, "someString");

return preparedStatement;

}

这在使用以下资源尝试的方法中调用:

try (Connection connection = getConnection();
    PreparedStatement preparedStatement =
        getPreparedStatement(connection)) {//stuff}

现在我假设准备好的语句将被自动关闭,因为它是在资源尝试中启动的。但是 SonarCloud 说我应该在 getPreparedStatement 方法中对资源使用 try 或在 finally 块中关闭 PreparedStatement。这是 SonarCloud 的错误发现还是有更好的方法呢?

4

2 回答 2

1

getConnection应该抛出异常而不是返回null。返回null是不好的. SonarCloud seems to be wanting you to put a try-with-resource opening ingetPreparedStatement (must include thesetString`) 并在调用方法中关闭,当然你不能这样做。

最好的方法是Execute Around 成语。而不是getPreparedStatement返回PreparedStatement要执行的 lambda(通常)传递。然后可以在 try-with-resource 语句中干净地关闭资源。

/*** NICE ***/
// Function instead of Consumer would allow the method to return a value.
private void prepared(
    Connection connection, Consumer<PreparedStatement> op
) throws SQLException {
    // Might want to add getConnection in here too, perhaps.
    try (
        PreparedStatement statement =
             connection.prepareStatement(SQL)
    ) { 
        statement.setString(1, "someString");
        op.accept(statement);
    }
}

用作:

    try (Connection connection = getConnection()) {
        prepared(connection, statement -> {
            // blah, blah, blah
        });
    }

getPreparedStatementhacky 的替代方法是在仅在错误条件下关闭的 try 语句中包含一条语句。

/*** HACKY ***/
private PreparedStatement prepared(
    Connection connection
) throws SQLException {
    boolean success = false;
    PreparedStatement statement =
        connection.prepareStatement(SQL);
    try { 
        statement.setString(1, "someString");
        success = true;
        return preparedStatement;
    } finally {
        if (!success) {
            statement.close();
        }
    }
}

如果您非常想getConnection返回null(不要)并使用单个两个条目的 try-with-resource,那么条件运算符就可以工作。

try (
    Connection connection = getConnection();
    PreparedStatement statement =
        connection==null ? null : connection.prepareStatement(SQL)
) {
于 2020-02-28T14:41:28.217 回答
0

最简单的方法和 IMO 最易读的方法是使用 2 个 try-with-resources 块。即使是声纳也有一个内置的例外,即不允许嵌套的 try-catch-blocks 用于这个用例......

try (Connection conn = getConnection()) {
    if (conn != null) {
        try (PreparedStatement stmt = ...) {
            // do stuff
        }
    }
}

如果do stuff很长,它可以并且应该被重构为一个单独的方法(可能包括内部的 try-with-resources)。

于 2020-02-28T14:59:45.510 回答