我应该如何在JDBC中使用try-with-resources?

我有一个使用JDBC从数据库中获取用户的方法:

public List<User> getUser(int userId) { String sql = "SELECT id, name FROM users WHERE id = ?"; List<User> users = new ArrayList<User>(); try { Connection con = DriverManager.getConnection(myConnectionURL); PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, userId); ResultSet rs = ps.executeQuery(); while(rs.next()) { users.add(new User(rs.getInt("id"), rs.getString("name"))); } rs.close(); ps.close(); con.close(); } catch (SQLException e) { e.printStackTrace(); } return users; } 

我应该如何使用Java 7 试用资源来改进此代码?

我已经尝试了下面的代码,但它使用了很多try ,并没有提高可读性 。 我应该以另一种方式使用try-with-resources吗?

 public List<User> getUser(int userId) { String sql = "SELECT id, name FROM users WHERE id = ?"; List<User> users = new ArrayList<>(); try { try (Connection con = DriverManager.getConnection(myConnectionURL); PreparedStatement ps = con.prepareStatement(sql);) { ps.setInt(1, userId); try (ResultSet rs = ps.executeQuery();) { while(rs.next()) { users.add(new User(rs.getInt("id"), rs.getString("name"))); } } } } catch (SQLException e) { e.printStackTrace(); } return users; } 

我意识到这是很久以前的答案,但要提出一个避免嵌套尝试与资源双重块的方法。

 public List<User> getUser(int userId) { try (Connection con = DriverManager.getConnection(myConnectionURL); PreparedStatement ps = createPreparedStatement(con, userId); ResultSet rs = ps.executeQuery()) { // process the resultset here, all resources will be cleaned up } catch (SQLException e) { e.printStackTrace(); } } private PreparedStatement createPreparedStatement(Connection con, int userId) throws SQLException { String sql = "SELECT id, username FROM users WHERE id = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, userId); return ps; } 

在你的例子中不需要外部尝试,所以你至less可以从3下降到2,也不需要closures; 在资源列表的末尾。 使用两个try块的好处是你所有的代码都在前面,所以你不必引用一个单独的方法:

 public List<User> getUser(int userId) { String sql = "SELECT id, username FROM users WHERE id = ?"; List<User> users = new ArrayList<>(); try (Connection con = DriverManager.getConnection(myConnectionURL); PreparedStatement ps = con.prepareStatement(sql)) { ps.setInt(1, userId); try (ResultSet rs = ps.executeQuery()) { while(rs.next()) { users.add(new User(rs.getInt("id"), rs.getString("name"))); } } } catch (SQLException e) { e.printStackTrace(); } return users; } 

怎么样创build一个额外的包装类?

 package com.naveen.research.sql; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public abstract class PreparedStatementWrapper implements AutoCloseable { protected PreparedStatement stat; public PreparedStatementWrapper(Connection con, String query, Object ... params) throws SQLException { this.stat = con.prepareStatement(query); this.prepareStatement(params); } protected abstract void prepareStatement(Object ... params) throws SQLException; public ResultSet executeQuery() throws SQLException { return this.stat.executeQuery(); } public int executeUpdate() throws SQLException { return this.stat.executeUpdate(); } @Override public void close() { try { this.stat.close(); } catch (SQLException e) { e.printStackTrace(); } } } 

然后在调用类中,您可以实现prepareStatement方法为:



     (Connection con = DriverManager.getConnection(JDBC_URL,prop);
                         PreparedStatementWrapper stat = new PreparedStatementWrapper(con,query,new Object [] {123L,“TEST”}){
                             @覆盖
                             protected void prepareStatement(Object ... params)throws SQLException {
                                 stat.setLong(1,Long.class.cast(params [0]));
                                 stat.setString(2,String.valueOf(params [1]));
                             }
                         };
                         ResultSet rs = stat.executeQuery();
                         ){
                            而(rs.next()) 
                                 System.out.println(String.format(“%s,%s”,rs.getString(2),rs.getString(1)));
                 catch(SQLException e){
                     e.printStackTrace();
                 }

下面是使用lambdas和JDK 8供应商的一个简洁的方法来适应外部尝试中的所有事情:

  try (Connection con = DriverManager.getConnection(JDBC_URL, prop); PreparedStatement stmt = ((Supplier<PreparedStatement>)() -> { try { PreparedStatement s = con.prepareStatement( "SELECT userid, name, features FROM users WHERE userid = ?"); s.setInt(1, userid); return s; } catch (SQLException e) { throw new RuntimeException(e); } }).get(); ResultSet resultSet = stmt.executeQuery()) { }