Comment dois-je utiliser try-with-resources avec JDBC?

J’ai une méthode pour obtenir des utilisateurs d’une firebase database avec JDBC:

public List getUser(int userId) { Ssortingng sql = "SELECT id, name FROM users WHERE id = ?"; List users = new ArrayList(); 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.getSsortingng("name"))); } rs.close(); ps.close(); con.close(); } catch (SQLException e) { e.printStackTrace(); } return users; } 

Comment utiliser Java 7 try-with-resources pour améliorer ce code?

J’ai essayé avec le code ci-dessous, mais il utilise beaucoup d’ try et n’améliore pas beaucoup la lisibilité . Dois-je utiliser try-with-resources d’une autre manière?

 public List getUser(int userId) { Ssortingng sql = "SELECT id, name FROM users WHERE id = ?"; List 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; } 

    Je me rends compte que cela a été il y a longtemps, mais je veux suggérer une approche supplémentaire qui évite le double bloc nested try-with-resources.

     public List 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 { Ssortingng sql = "SELECT id, username FROM users WHERE id = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, userId); return ps; } 

    Il n’y a pas besoin d’essayer l’extérieur dans votre exemple, donc vous pouvez au moins descendre de 3 à 2, et vous n’avez pas non plus besoin de fermer ; à la fin de la liste de ressources. L’avantage de l’utilisation de deux blocs d’essai est que tout votre code est présent à l’avant, de sorte que vous n’avez pas à vous référer à une méthode distincte:

     public List getUser(int userId) { Ssortingng sql = "SELECT id, username FROM users WHERE id = ?"; List 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; } 

    Voici un moyen concis d’utiliser lambdas et le fournisseur JDK 8 pour tout adapter à l’essentiel:

      try (Connection con = DriverManager.getConnection(JDBC_URL, prop); PreparedStatement stmt = ((Supplier)() -> { 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()) { } 

    Qu’en est-il de la création d’une classe wrapper supplémentaire?

     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, Ssortingng 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(); } } } 

    Ensuite, dans la classe appelante, vous pouvez implémenter la méthode prepareStatement comme suit:

     try (Connection con = DriverManager.getConnection(JDBC_URL, prop); PreparedStatementWrapper stat = new PreparedStatementWrapper(con, query, new Object[] { 123L, "TEST" }) { @Override protected void prepareStatement(Object... params) throws SQLException { stat.setLong(1, Long.class.cast(params[0])); stat.setSsortingng(2, Ssortingng.valueOf(params[1])); } }; ResultSet rs = stat.executeQuery();) { while (rs.next()) System.out.println(Ssortingng.format("%s, %s", rs.getSsortingng(2), rs.getSsortingng(1))); } catch (SQLException e) { e.printStackTrace(); }