2

在 Java 中执行一条 SQL 语句涉及许多步骤:

  1. 创建连接
  2. 创建语句
  3. 执行语句,创建结果集
  4. 关闭结果集
  5. 关闭声明
  6. 关闭连接

在每个步骤中都可能抛出 SQLException。如果我们能够正确处理所有异常并释放所有资源,代码将如下所示,其中 4 级 TRY 堆叠在彼此的顶部。

try {
     Connection connection = dataSource.getConnection();
     try {
           PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM myTable");
           try {
                ResultSet result = statement.executeQuery();
                try {
                     if (result.next()) {
                           Integer theOne = result.getInt(1);
                     }
                }
                finally {
                     result.close();
                }
           }
           finally {
                statement.close();
           }
     }
     finally {
           connection.close();
     }
}
catch (SQLException e) {
// Handle exception
}

您能否提出一种更好(更短)的方式来执行语句,同时释放所有消耗的资源?

4

6 回答 6

8

如果您使用的是 Java 7,try with resources语句将大大缩短这一点,并使其更易于维护:

try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(queryString); ResultSet rs = ps.execute()) {

} catch (SQLException e) {
    //Log the error somehow
}

请注意,关闭连接会关闭所有关联的StatementsResultSets

于 2012-12-05T14:40:25.143 回答
4

查看Apache Commons DbUtils,尤其是closeQuietly()方法。它将正确处理连接/语句/结果集关闭,包括一个或多个为空的情况。

另一种选择是Spring JdbcTemplate,它可以从您那里抽象出很多工作,并且您可以以更实用的方式处理数据库查询。您只需提供一个类作为回调,以便为 a 的每一行调用ResultSet。它将处理迭代、异常处理和正确关闭资源。

于 2012-12-05T14:40:13.487 回答
0

我使用可以调用的静态方法创建了一个实用程序类:

package persistence;

// add imports.

public final class DatabaseUtils {

    // similar for the others Connection and Statement
    public static void close(ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (Exception e) {
            LOGGER.error("Failed to close ResultSet", e);
        }
    }
}

所以你的代码是:

     Integer theOne = null;
     Connection connection = null;
     PreparedStatement statment = null;
     ResultSet result = null;
     try {
         connection = dataSource.getConnection();
         statement = connection.prepareStatement("SELECT 1 FROM myTable");
         result = statement.executeQuery();
         while (result.next()) {
             theOne = result.getInt(1);
         }
    } catch (SQLException e) {
        // do something
    } finally {
        DatabaseUtils.close(result);
        DatabaseUtils.close(statement);
        DatabaseUtils.close(connection);
    }
    return theOne;

我建议在此方法之外实例化 Connection 并将其传入。您可以通过这种方式更好地处理事务。

于 2012-12-05T14:39:43.377 回答
0

只需关闭Connection,这将释放所有资源*。您不需要关闭Statementand ResultSet

*只要确保您没有任何活跃的交易。

于 2012-12-05T14:43:36.900 回答
0
Connection connection = null;
PreparedStatement statement = null;
ResultSet result = null;
try {
     connection = dataSource.getConnection(); 
     statement = connection.prepareStatement("SELECT 1 FROM myTable");
     result = statement.executeQuery();
     if (result.next()) {
         Integer theOne = result.getInt(1);
     }
}
catch (SQLException e) { /* log error */ }
finally {           
     if (result != null) try { result.close(); } catch (Exception e) {/*log error or ignore*/}
     if (statement != null) try { statement.close(); } catch (Exception e) {/*log error or ignore*/}
     if (connection != null) try { connection.close(); } catch (Exception e) {/*log error or ignore*/}
}
于 2012-12-05T14:48:34.080 回答
0

您的代码可以缩短并以这种方式编写...

Connection connection = dataSource.getConnection();
PreparedStatement statement = null;
ResultSet result = null;
try {
    statement= connection.prepareStatement("SELECT 1 FROM myTable");
    result = statement.executeQuery();
    if (result.next()) {
        Integer theOne = result.getInt(1);
    }
} catch (SQLException e) {
    // Handle exception

} finally {
    if(result != null) result.close();
    if(statement != null) statement.close();
    if(connection != null) connection.close();
}
于 2012-12-05T14:48:58.480 回答