Получение больших списков объектов с помощью Java EE - PullRequest
3 голосов
/ 05 января 2011

Существует ли общепринятый способ возврата большого списка объектов с использованием Java EE?

Например, если бы у вас была база данных ResultSet с миллионами объектов, как бы вы вернули эти объекты (удаленному) клиентскому приложению?

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

Поскольку все данные не могут поместиться в памяти, я подумал, что комбинация SessionBean с состоянием и какого-то другого пользовательского итератора, который вызывает сервер, поможет.

Итак, другими словами, если у меня есть API, такой как Iterator<Data> getData(), то какой хороший способ реализовать getData() и Iterator<Data>?

Как вы успешно решили эту проблему в прошлом?

Ответы [ 3 ]

2 голосов
/ 05 января 2011

Определенно не копируйте всю БД в память Java. Это не имеет никакого смысла и только делает вещи излишне медленными и запирающими память. Скорее ввести нумерацию страниц на уровне базы данных. Вам следует запрашивать только те данные, которые на самом деле должны отображаться на текущей странице, как это делает Google.

Если вам действительно трудно реализовать это правильно и / или определить запрос SQL для конкретной базы данных, взгляните на этот ответ . Для эквивалента JPA / Hibernate, посмотрите на этот ответ .


Обновление в соответствии с комментариями (что фактически меняет всю тему вопроса ...), вот базовый (псевдо) стартовый пример:

List<Source> inputSources = createItSomehow();
Source outputSource = createItSomehow();

for (Source inputSource : inputSources) {
    while (inputSource.next()) {
        outputSource.write(inputSource.read());
    }
}

Таким образом, вы фактически получаете одну запись в памяти Java вместо всей коллекции, как в следующем (неэффективном) примере:

List<Source> inputSources = createItSomehow();
List<Entry> entries = new ArrayList<Entry>();

for (Source inputSource : inputSources) {
    while (inputSource.next()) {
        entries.add(inputSource.read());
    }
}

Source outputSource = createItSomehow();

for (Entry entry : entries) {
    outputSource.write(entry);
}
1 голос
/ 06 января 2011

Нумерация страниц - хорошее решение при работе с веб-интерфейсом. иногда, однако, гораздо эффективнее передавать все за один вызов. библиотека rmiio была написана специально для этой цели, и уже известно, что она работает на различных серверах приложений.

0 голосов
/ 05 января 2011

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

Итак, в основном, вы делаете пейджинг и используете пакетное чтение. Допустим, вы загружаете 1 тыс. объектов из вашей базы данных, отправляете их клиенту на запрос ответа. И вы зацикливаетесь, пока не обработаете все объекты. (См. Ответ от BalusC)

Проблема такая же на стороне клиента, и вам, скорее всего, придется передавать данные в файловую систему для предотвращения ошибок OutOfMemory.

Обратите также внимание: можно загружать миллионы объектов из базы данных в качестве административной задачи: например, для выполнения резервного копирования и экспорта некоторых «исключительных» случаев. Но вы не должны использовать его как запрос, который может сделать любой пользователь. Это будет медленно и истощать ресурсы сервера.

...