【问题标题】:How to properly use try-with-resources in Database connection?如何在数据库连接中正确使用 try-with-resources?
【发布时间】:2020-01-08 12:54:27
【问题描述】:

我环顾四周,但似乎找不到我的问题的答案。

这里是上下文:我必须在我的 Java 程序中连接到数据库并执行我无法控制且事先不知道的 SQL 请求。为此,我使用下面的代码。

public Collection<HashMap<String, String>> runQuery(String request, int maxRows) {

    List<HashMap<String, String>> resultList = new ArrayList<>();

    DataSource datasource = null;

    try {

        Context initContext = new InitialContext();
        datasource = (DataSource) initContext.lookup("java:jboss/datasources/xxxxDS"); 

    } catch (NamingException ex) {

        // throw something.
    }

    try (Connection conn = datasource.getConnection();
         Statement statement = conn.createStatement();
         ResultSet rs = statement.executeQuery(request); ) {

        while (rs.next()) 
        {
            HashMap<String, String> map = new HashMap<>();

            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                map.put(rs.getMetaData().getColumnName(i).toUpperCase(), rs.getString(i));
            }

            resultList.add(map);             
        }

    } catch (SQLException ex) {

        // throw something.
    }

    return resultList;       
}

我面临的问题是: 如您所见,我不使用另一个参数maxRows。我需要将此指定给statement,但不能在try-with-resources 中执行。

我想通过在第一个方法中嵌套另一个try-with-resources 来避免增加这种方法的认知复杂性,以指定最大行数(就像在这个代码示例中一样)。

try (Connection conn = datasource.getConnection();
 Statement statement = conn.createStatement(); ) {

    statement.setMaxRows(maxRows);

    try (ResultSet rs = statement.executeQuery(request); ) {

        while (rs.next()) 
        {
            HashMap<String, String> map = new HashMap<>();

            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                map.put(rs.getMetaData().getColumnName(i).toUpperCase(), rs.getString(i));
            }

            resultList.add(map);             
        }
    }

} catch (SQLException ex) {

    // throw something.
}

有没有办法只用一个try-with-resources

【问题讨论】:

  • 您可以创建一个单独的方法来创建一个语句和setMaxRows。类似于this 回答中的方法
  • 您不必关闭 ResultSet。关闭一个 Statement 将自动关闭它的 ResultSet。来自the documentation:“当Statement 对象关闭时,其当前的ResultSet 对象(如果存在)也将关闭。”
  • @VGR 哦,我浏览文档时没有看到注释,感谢您指出!请注意,Sonar 不了解文档,如果您将其从 try 中删除,您应该使用 try-with-resources
  • 这就是为什么 Sonar 和任何其他代码分析工具都不应该被视为最佳实践的最终决定。
  • 你说得对!

标签: java connection try-with-resources code-complexity


【解决方案1】:

如果您可以选择其他方法,那么只需一个 try-resources 即可

而不是Statement statement = conn.createStatement();

Statement statement = createStatement(conn, maxRows);

在这个新方法中,创建 Statement 对象并设置 maxRows 并返回语句 obj。

【讨论】:

    【解决方案2】:

    您可以在单个 try-with-resources 块中添加一个辅助方法来执行此操作:

        private static <T, E extends Exception> T configured(T resource, ThrowingConsumer<? super T, E> configuration) throws E {
            configuration.accept(resource);
            return resource;
        }
    
        private interface ThrowingConsumer<T, E extends Exception> {
    
            void accept(T value) throws E;
        }
    

    并像这样使用它:

            try (Connection conn = null
                  ; Statement statement = configured(conn.createStatement(), stmt -> stmt.setMaxRows(maxRows))
                  ; ResultSet rs = statement.executeQuery(request)) {
    
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 2017-09-28
      • 2019-01-18
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多