Как правильно перебирать записи БД с помощью Hibernate - PullRequest
3 голосов
/ 21 декабря 2011

Я хочу перебрать записи в базе данных и обновить их.Однако, поскольку это обновление занимает некоторое время и подвержено ошибкам, мне нужно: а) не заставлять db ждать (как, например, с ScrollableResults) и б) фиксировать после каждого обновления.Во-вторых, это делается в нескольких потоках, поэтому я должен убедиться, что, если поток A заботится о записи, поток B получает другую.Как я могу реализовать это разумно с Hibernate?

Чтобы дать лучшую идею, следующий код будет выполняться несколькими потоками, где все потоки совместно используют один экземпляр RecordIterator:

Iterator<Record> iter = db.getRecordIterator();
while(iter.hasNext()){
    Record rec = iter.next();
    // do something lengthy here
    db.save(rec);
}

Так что мой вопрос в том, как реализовать RecordIterator.Если на каждом next() я выполняю запрос, как обеспечить, чтобы я не возвращал одну и ту же запись дважды?Если нет, какой запрос использовать для возврата отдельных объектов?Есть ли недостаток в общем подходе (например, использовать один RecordIterator на поток и позволить БД как-то обрабатывать синхронизацию)?Дополнительная информация: существует множество способов локально хранить их (например, в наборе обработанных записей).

Обновление: Поскольку весь процесс занимает некоторое время, может случиться, чтостатус записей меняется.В связи с этим порядок следования запроса может измениться.Я думаю, чтобы решить эту проблему, я должен пометить записи в базе данных, как только я возвращаю их для обработки ...

Ответы [ 2 ]

2 голосов
/ 21 декабря 2011

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

В вашем ридере сделайте пейджинг с помощью setFirstResult / setMaxResults. Например. если в вашей очереди максимум 1000 элементов, заполните их до 500 за раз. Когда очередь заполнится, следующее нажатие автоматически подождет, пока средства обновления не получат следующие элементы.

0 голосов
/ 21 декабря 2011

Мое предложение будет, поскольку вы совместно используете экземпляр главного итератора, это запустить все ваши потоки, используя общую транзакцию Hibernate, с одной загрузкой в ​​начале и большим сохранением в конце.Вы загружаете все свои данные в один «Set», который вы можете перебирать, используя свои потоки (будьте осторожны с блокировками, так что вы можете захотеть разделить раздел для каждого потока или каким-то образом управлять общим ресурсом так, чтобы вы не делали это).t overlap).

Прелесть решения Hibernate заключается в том, что записи не сразу сохраняются в базе данных, поскольку вы используете транзакцию, и хранятся в кеше hibernate.Затем, в конце концов, они все сразу будут записаны обратно в базу данных.Это сэкономит на тех дорогих записях в базе данных, которые вас беспокоят, плюс к тому, что вы получите фактический объект для работы на каждой итерации, а не просто строку базы данных.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...