Как я могу получить ResultSet JDBC как ArrayList? - PullRequest
15 голосов
/ 13 марта 2009

Я делаю запрос для получения большого количества идентификаторов (целых чисел). Вместо того чтобы миллионы раз перебирать ResultSet и копировать все по одному в ArrayList, есть ли способ просто извлечь все как ArrayList?

Я понимаю, что ResultSet должен быть итеративным, потому что базовая реализация может быть связана с кэшированием, но в моей ситуации мне просто нужны все идентификаторы сразу. Я знаю, что могу установить FetchSize на большое число, но тогда мне все равно придется извлекать идентификаторы один за другим.

Разъяснение: причина, по которой я хочу это сделать, - производительность. Профилирование показывает, что выполнение ResultSet.next (), ResultSet.getInt () и ArrayList.add () миллионы раз занимает довольно много времени. Я полагаю, что база данных (я использую H2, которая написана на Java), вероятно, имеет массив или список где-то в памяти, поэтому я ищу способ скопировать его мне напрямую, а не через итерационный интерфейс ResultSet .

Ответы [ 3 ]

17 голосов
/ 13 марта 2009

Используя библиотеку 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;
}
6 голосов
/ 13 марта 2009

Поместите код в метод. Вызывать методы очень просто ...

С макушки головы:

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);

Готово.

5 голосов
/ 13 марта 2009

Если у вас проблема с низкой производительностью, настройте оператор, прежде чем выполнять его с помощью

java.sql.Statement.setFetchSize(int)

Поэкспериментируйте с 100, 1000, 10000, .. Это позволит избежать ненужных циклических переходов, которые могут быть причиной упомянутой вами медленности.

Кроме того, ArrayList.add () может быть медленным, если он должен многократно изменять размер внутреннего массива, поскольку он создает новый массив и копирует туда все данные. Вместо этого попробуйте LinkedList.

...