2011-01-14 2 views
0

Учитывая следующую ситуацию:Streaming DAO Результаты в Java (Design Pattern)

  • DAO, который запрашивает все строки из таблицы и отображает их в список объектов предметной области (чистый JDBC)
  • сервис, который обрабатывает список, полученный из DAO, и отображает определенные элементы списка, отформатированные в файле.

Проблема в том, что все результаты DAO хранятся в памяти, что становится опасным по мере роста таблиц.

Вопрос: Есть ли образец для чтения объектов из DAO потоковым способом, который служба обрабатывает только один элемент за раз, записывает его в выходной поток файла и затем запрашивает следующий элемент из набора результатов ? Является ли вообще хорошей идеей использовать ResultSet как возвращаемый тип DAO?

ответ

4

Даже если вы выставили набор результатов, которого вы не должны, по-прежнему не получите потоковой семантики по умолчанию. Для этого вам нужно сделать что-то вроде этого:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, 
       java.sql.ResultSet.CONCUR_READ_ONLY); 
stmt.setFetchSize(Integer.MIN_VALUE); 

Вы должны инкапсулировать это в пределах вашего DAO, вы можете вернуть пользовательский итератор для обработки результатов.

См. mysql reference на тему потоковых результатов.

+0

Thx! У меня было такое же ощущение, что не стоит показывать ResultSets. Итератор - хороший совет! Тем не менее, мне интересно, стоит ли просто отделить (немного) BL от логики запросов БД. Я предполагаю, что в целом люди просто смешивают это в одном классе? – david

+0

Обычно логика BL и DB не переплетается. Возвращение пользовательского итератора из вашего DAO будет самым простым и чистым решением. – Joel

+0

Абсолютно согласен! – david

0

Итак, вы обрабатываете только одну строку только один раз? Вы можете пометить эту строку как обработанную в базе данных и выбрать только строки, которые не обрабатываются. Кроме того, вы можете перемещать обработанные строки в другую таблицу.

+0

Ваши предложения будут содержать хотя бы одно обновление для каждой строки. Это звучит не очень хорошо, когда у вас есть, например, около 100 тыс. или миллион строк. – david

+0

Хорошая точка. Другие варианты на этой странице выглядят намного более желательными. – TrueDub

1

Лучший способ - выполнить постраничный запрос, вы можете получить общее количество строк, а затем выбрать размер страницы и использовать инструменты базы данных (rowid for oracle), чтобы получить страницы, пока у вас не будет всех строк, или вы можете просто продолжайте запрашивать, пока не получите никаких результатов.

+0

Как будет выглядеть интерфейс DAO? Пожалуйста, имейте в виду, что я хотел бы сохранить разделение между бизнес-логикой (Service) и логикой запросов (DAO). – david

0

Я бы никогда не возвратил ResultSet из DAO, сохраните логику данных, инкапсулированную в класс данных.

Я бы, вероятно, никогда не писал метод DAO, который возвращал всю таблицу, кажется просто слишком общим. Вместо этого я, вероятно, напишу метод DAO под названием dumpToFile(File f), который сделал всю работу внутри. Таким образом, DAO может читать записи по одному и записывать их в файл.

+0

Предположим, что служба выполняет определенные проверки, пропуская некоторые записи из-за бизнес-правил и форматируя их. При применении концепции разделения проблем это не должно делаться в DAO. Вот почему я спрашиваю. – david