在try-with-resources块中调用对象的方法

时间:2016-01-15 08:48:30

标签: java prepared-statement try-with-resources autocloseable

Java tutorial表示您可以使用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(这是我试图避免的)。我意识到没有什么是错的'这样做,我只想为了便于阅读而这样做。
  2. 考虑以下情况:

    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) {
        ...
    }
    

    VS

    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. 创建某种辅助方法,创建连接并相应地设置参数。
    3. 类似的东西:

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

3 个答案:

答案 0 :(得分:3)

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

由于Statement.close的API-Doc保证关闭其ResultSet,因此无需明确关闭ResultSet。所以写的很好

try (PreparedStatement stmt = con.prepareStatement(query)) {
    stmt.setString(1, name);
    ResultSet rs = stmt.executeQuery(query);
    ...
}
catch (SQLException e) {
    ...
}

答案 1 :(得分:1)

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

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

答案 2 :(得分: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 {
        }
    }

}

它是如何工作的:

在 try catch 资源中,一切都应该返回一个从 Object 接口实现的 AutoClosable。此类仅返回您在使用方法工作后传递的相同对象(在 lambda 中)