2

Java 教程声明您可以使用以下方法执行以下操作try-with-resources

try (Statement stmt = con.createStatement()) {
    ResultSet rs = stmt.executeQuery(query);
    ...
} catch (SQLException e) {
    ...
}

在本教程中,ResultSet永远不会关闭,因此我想包含ResultSet,因为它也实现了AutoCloseable接口,如下所示:

try (Statement stmt = con.createStatement(); 
     ResultSet rs = stmt.executeQuery(query)) {
    ...
} catch (SQLException e) {
    ...
}

这很好用,但是当涉及到PreparedStatements我希望能够在执行查询之前设置一些值时:

String name = "Ian";
try (PreparedStatement pstmt = getPreparedStatement(con, stmt); 
     pstmt.setString(1, name);
     ResultSet rs = pstmt.executeQuery(query)) {
    ...
} catch (SQLException e) {
    ...
}

这会导致一系列编译错误,因为(我假设)只允许变量赋值。

try-with-resources有没有办法在同一个街区巧妙地做到这一点?

我已经想到了:

  1. 嵌套的 try-with-resources (这是我试图避免的)。我意识到这样做并没有什么“错误”,我只是为了可读性而这样做。

考虑以下情况:

try (MyObject1 o1 = new MyObject1()) {
    o1.setSomeValue();
    try (MyObject2 o2 = new MyObject2(o1)) {
        o2.setSomeValue();
        try (MyObject3 o3 = new MyObeject3(o2) {
            o3.setSomeValue();
            // do work here
        }
    }
} catch (Exception e) {
    ...
}

对比

try (MyObject1 o1 = new MyObject1();
     o1.setSomeValue();
     MyObject3 o2 = new MyObeject2(o1);
     o2.setSomeValue();
     MyObject3 o3 = new MyObeject3(o2);
     o3.setSomeValue()) {

    // do work here
} catch (Exception e) {
    ...
}
  1. setString()方法返回对象并将其包含在赋值中
  2. 创建某种帮助方法来创建连接并相应地设置参数。

就像是:

public PreparedStatement createPreparedStatement(Connection con, String stmt, Object ... params) {

}
4

3 回答 3

3

我猜你的意思是Connection.prepareStatement()

无需显式关闭 ResultSet,因为 API-DocStatement.close保证关闭其 ResultSet。所以写就好了

try (PreparedStatement stmt = con.prepareStatement(query)) {
    stmt.setString(1, name);
    ResultSet rs = stmt.executeQuery(query);
    ...
}
catch (SQLException e) {
    ...
}
于 2016-01-15T09:20:26.380 回答
1

如果你想在构造Statement和 之间设置一些值,ResultSet你将需要嵌套的 try-with-resources 块。你为什么要避免这种情况?这样做并没有错。

您可以定义一些笨重的辅助方法,但除了一些非常高使用率的情况外,这将比它的价值更麻烦。

于 2016-01-15T08:55:00.350 回答
0

你可以这样:

try (
     Connection con = em.unwrap(Connection.class);
     PreparedStatement ps = TryJumper.jump(con.prepareStatement("select * from x where a = ?"), pss -> {
         pss.setInt(1, 123);
     });
     ResultSet rs = ps.getResultSet();
) {
    //core codes
} catch (Exception e) {
    e.printStackTrace();
}

必要的课程

public class TryJumper {

    public static <M> M jump(M m, MUser<M> mUser) throws Exception {
        mUser.consume(m);
        return m;
    }

    interface MUser<M> extends AutoCloseable {
        void consume(M m) throws Exception;

        @Override
        default void close() throws Exception {
        }
    }

}

它是如何工作的:

在尝试捕获资源中,所有内容都应从接口返回Object哪个实现。AutoClosable此类仅返回您在使用方法工作后传递的相同对象(在lambda

于 2021-06-17T15:42:29.373 回答