如何将 JDBC ResultSet 检索为 ArrayList?

Posted

技术标签:

【中文标题】如何将 JDBC ResultSet 检索为 ArrayList?【英文标题】:How can I retrieve a JDBC ResultSet as an ArrayList? 【发布时间】:2010-10-13 03:17:58 【问题描述】:

我正在执行查询以检索大量 ID(整数)。与其通过 ResultSet 迭代数百万次并将所有内容逐个复制到 ArrayList 中,有什么方法可以简单地将所有内容作为 ArrayList 检索?

我知道 ResultSet 应该被迭代,因为底层实现可能是缓存的东西,但在我的情况下,我只需要所有的 ID。我知道我可以将 FetchSize 设置为一个很大的数字,但是我仍然需要一个接一个地检索 ID。

澄清:我想这样做的原因是性能。分析向我展示了数百万次执行 ResultSet.next()、ResultSet.getInt() 和 ArrayList.add() 需要相当长的时间。我认为数据库(我使用的是用 Java 编写的 H2)可能在内存中的某处有数组或列表,所以我正在寻找一种方法将其直接复制给我,而不是通过 ResultSet 迭代接口.

【问题讨论】:

可能处理数百万个整数需要很长时间。你想要一个 int[] 或原始的 List 类代替吗?由于更新和一般表格性,可能没有直接作为 int/List 实现。 int[] 或 List 都可以。我基本上只是在寻找一种对数据库说的方法:忘记缓存/延迟加载等,尽快给我数据:) 有一个配置文件,看看性能问题在哪里。 (Oracle 在其 ResultSet IIRC 上确实有获取列数组方法。这对 H2 来说并不重要。) 【参考方案1】:

使用 Apache DbUtils 库,您可以轻松地将 ResultSet 作为地图列表返回。

public List query(String query) 
    List result = null;
    try 
        QueryRunner qrun = new QueryRunner();
        result = (List) qrun.query(connection, query, new MapListHandler());
     catch (Exception ex) 
        ex.printStackTrace();
    
    return result;

【讨论】:

这不会胜过 JDBC 本身吗?同意,它看起来更方便,但肯定不是更快......? DbUtils 是一个辅助库,所以你还在使用 JDBC。查看他们的网站,了解使用 DbUtils 的一些优势。 commons.apache.org/dbutils 我了解,但在您回答后,OP 似乎改变了问题。他们正在寻找绕过 JDBC API 的方法,以提高性能... 在不知道 OP 对 ID 做了什么的情况下很难回答。我不会考虑优化迭代,而是尝试找出一种方法来完成相同的任务,这样就不需要使用数百万个 ID 填充本地数据结构。 @LukasEder 我所知道的所有 Java 数据库访问机制(JDO/JPA/DBUtils)实际上都是 JDBC。【参考方案2】:

将代码放入方法中。调用方法很简单……

在我的头顶:

public static List<Integer> readInts(
     PreparedStatement statement
) throws SQLException 
     ResultSet results = statement.executeQuery();
     try 
         assert results.getMetaData().getColumnCount() == 1;

         List<Integer> ints = new ArrayList<Integer>();
         while (results.next()) 
             ints.add(Integer.valueOf(results.getInt(1)));
         
         return ints;
      finally 
         results.close();
     

那么就叫它:

List<Integer> ids = readInts(myStatemnet);

完成。

【讨论】:

这无助于提高您仍在循环数据的性能。我相信他只是想甩掉它。 如何在不循环数据的情况下“转储”它? (顺便说一句,问题的最后一段不在原文中。)【参考方案3】:

如果您的问题是性能不佳,请在执行之前调整语句

java.sql.Statement.setFetchSize(int)

用 100, 1000, 10000,.. 进行实验。这样可以避免不必要的往返,这可能是您提到的缓慢的原因。

此外,如果必须多次调整内部数组的大小,ArrayList.add() 可能会很慢,因为它会创建一个新数组并将所有数据复制到那里。改用 LinkedList。

【讨论】:

如果您知道要使用的获取大小,您还可以在 ArrayList 构造函数中声明其内部数组的初始大小为相同数量。 @Daddy 据我了解,问题的作者将所有返回的 ID 添加到一个列表中。这意味着您的建议真的没有帮助,除非您创建一个具有结果集的完整大小的数组,而不仅仅是 fetchsize。 @Deckard,这个问题仍然没有被接受的答案,你解决了这个问题吗? @monty024 不。不幸的是,JDBC 根本没有公开这样的结构,所以唯一可能的方法是如果某些 Java 实现的数据库会显式公开它。

以上是关于如何将 JDBC ResultSet 检索为 ArrayList?的主要内容,如果未能解决你的问题,请参考以下文章

将 JDBC ResultSet 映射到对象

如何使用 JDBC 检索数据

JDBC:如何从结果集中检索 SQL COUNT 函数的结果?

如何在 Spring JDBC ResultSetExtractor 中检查 ResultSet 是不是为空? [复制]

jdbc如何判断记录集是否为空?用啥方法?ResultSet本身是否根本就没有这样的方法?

hibernate中的query 如何能象jdbc中的resultset一样使用