Поддержка Spring JDBC и большой набор данных

При использовании одного из различных шаблонных методов JDBC я не понимаю, как выполнять итерацию / прокрутку больших наборов результатов (которые не помещаются в память). Даже без прямого доступа к интерфейсу Iterable я бы по крайней мере ожидал, что экземпляры RowCallbackHandler будут вызываться пока запрос выполняется не после его завершения (или переполнения кучи).

Я взглянул на this (который ничего не изменил для меня, несмотря на то, что по духу похож на этот пост при переполнении стека) и на это сообщение на весенних форумах. Последнее, похоже, предполагает, что обработчик обратного вызова действительно должен вызываться, пока курсор извлекает данные. Однако мои тесты не показывают такого поведения.

База данных - Oracle10g. Я использую драйвер 11.1.0.7.0-Production и Spring 2.5.6.SEC01. Любые идеи, как перебирать наборы результатов, желательно при сохранении логики сопоставления RowMapper и т. Д.?


person yawn    schedule 27.08.2009    source источник


Ответы (5)


Драйвер Oracle JDBC имеет надлежащую поддержку метода setFetchSize() на java.sql.Statement, который позволяет вам контролировать, сколько строк драйвер будет извлекать за один раз.

Однако RowMapper, используемый Spring, работает, считывая каждую строку в память, заставляя RowMapper преобразовать ее в объект и сохраняя объект каждой строки в одном большом списке. Если ваш набор результатов огромен, то этот список станет большим, независимо от того, как JDBC извлекает данные строки.

Если вам нужно обрабатывать большие наборы результатов, RowMapper не масштабируется. Вместо этого вы можете рассмотреть возможность использования RowCallbackHandler вместе с соответствующими методами в JdbcTemplate. RowCallbackHandler не диктует, как будут храниться результаты, оставляя их на ваше усмотрение.

person skaffman    schedule 27.08.2009
comment
setFetchSize ничего не изменил для меня, я пробовал использовать его раньше. Вы разрабатываете на основе экземпляра Oracle? Для меня RowCallBackHandler просто зависает, ожидая завершения запроса, как я написал в своем OP. - person yawn; 27.08.2009
comment
По-видимому, я забыл вызов afterPropertiesSet () в шаблоне JDBC в моем тесте. Смущает, но теперь работает: *) - person yawn; 28.08.2009

Вы можете использовать библиотеку springjdbc-iterable:

CloseableIterator<MyObj> iter = jt.queryForIter("select ...", params, mapper);

Итератор будет автоматически закрываться при исчерпании ресурсов или может быть закрыт вручную. Он будет работать только в рамках транзакции.

Отказ от ответственности: я написал эту библиотеку

person alexkasko    schedule 10.12.2012

Это свойство драйвера / соединения, следует ли передавать данные обратно вам или отправлять их обратно одним фрагментом. Например, в SQL Server вы используете свойство SelectMethod в URL-адресе подключения:

jdbc:microsoft:sqlserver://gsasql03:1433;DatabaseName=my_db;SelectMethod=direct

Значение direct означает, что результаты должны быть получены за один раз. Другой вариант - cursor, который позволяет указать, что вы хотите, чтобы соединение возвращало вам результаты. Я не уверен, что такое аналог источника данных Oracle, боюсь

RowCallbackHandler, безусловно, работает для меня.

person oxbow_lakes    schedule 27.08.2009
comment
Да, в идеале вы не помещаете в набор данных, вы должны захватывать записи, сохраняя соединение открытым, спрашивая, есть ли еще записи. Я сделал это в .NET и получил неплохое улучшение производительности. Думаю, что-то подобное для java могло бы существовать, особенно весной. - person Zoidberg; 27.08.2009
comment
@ * Zoidberg * - OP, похоже, делает правильные вещи, используя обработчик обратного вызова строки - person oxbow_lakes; 27.08.2009
comment
Это звучит многообещающе. К сожалению, я не смог найти ничего похожего на этот параметр URL-адреса SQL Server в документации Oracle JDBC. - person yawn; 27.08.2009

  1. Создайте настраиваемую хранимую процедуру, расширяющую StoredProcedure
  2. Создайте RowCallBackHandler, который может обрабатывать каждую строку по одной.
  3. Объявите свои параметры. Если у вас есть набор результатов, сначала объявите его. Используйте класс SqlReturnResultSet и создайте его, используя свой RowCallBackHandler
  4. Объявите любые другие параметры
  5. Компилировать
  6. Я выполнил шаги со 2 по 5 в конструкторе хранимой процедуры моего клиента.
  7. Создайте карту, содержащую ваши входные параметры
  8. Выполните свои хранимые процедуры с входными параметрами

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

Вызов хранимых процедур с помощью шаблонов Spring JDBC

person Rob Breidecker    schedule 22.04.2016

вот хорошая библиотека для извлечения всех наборов результатов java sql в память.

http://casperdatasets.googlecode.com

вы можете прокручивать / перебирать набор данных, вы можете выполнять запросы к нему и создавать индексы для оптимизации. он также реализует интерфейс java.sql.resultset, поэтому вы можете продолжать работать с результатами из этого набора данных с минимальными изменениями в коде jdbc.

person jli_123    schedule 06.01.2011
comment
у него также есть адаптер, который преобразует набор результатов jdbc в набор результатов в памяти - я предполагаю, что вы можете вызвать этот адаптер в своем методе обратного вызова результатов spring jdbc. - person jli_123; 06.01.2011
comment
Извините, но как перебирать / прокручивать большие наборы результатов (которые не помещаются в память). - person yawn; 07.01.2011