Я пытаюсь разработать пакетный процесс, используя Spring Batch + Spring Boot (конфигурация Java), но у меня проблема с этим.У меня есть программное обеспечение, которое имеет базу данных и API Java, и я читаю записи оттуда.Пакетный процесс должен извлечь все документы, срок действия которых меньше определенной даты, обновить дату и снова сохранить их в той же базе данных.
Мой первый подход - чтение записей 100 на 100;поэтому ItemReader извлекает 100 записей, я обрабатываю их 1 на 1 и, наконец, пишу их снова.В считыватель я поместил этот код:
public class DocumentItemReader implements ItemReader<Document> {
public List<Document> documents = new ArrayList<>();
@Override
public Document read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if(documents.isEmpty()) {
getDocuments(); // This method retrieve 100 documents and store them in "documents" list.
if(documents.isEmpty()) return null;
}
Document doc = documents.get(0);
documents.remove(0);
return doc;
}
}
Итак, с этим кодом считыватель читает из базы данных, пока записи не найдены.Когда метод «getDocuments ()» не извлекает никаких документов, список пуст, и читатель возвращает ноль (поэтому задание завершено).Здесь все работало нормально.
Однако проблема возникает, если я хочу использовать несколько потоков.В этом случае я начал использовать подход Partitioner вместо многопоточности.Причина в том, что я читаю из одной и той же базы данных, поэтому, если я повторю полный шаг с несколькими потоками, все они найдут одинаковые записи, и я не смогу использовать нумерацию страниц (см. Ниже).
Другая проблема заключается в том, что записи базы данных обновляются динамически, поэтому я не могу использовать нумерацию страниц.Например, предположим, у меня есть 200 записей, и все они скоро истекают, поэтому процесс их извлечет.Теперь представьте, что я получаю 10 с одним потоком, и прежде всего этот поток обрабатывает один и обновляет его в той же базе данных.Следующий поток не может получить от 11 до 20 записей, так как первая запись не будет появляться в поиске (поскольку она была обработана, ее дата была обновлена, а затем она не соответствует запросу).
Это немного сложно понять, и некоторые вещи могут показаться странными, но в моем проекте:
- Я вынужден использовать одну и ту же базу данных для чтения и записи.
- У меня могут быть миллионы документов, поэтому я не могу прочитать все записи одновременно.Мне нужно прочитать их 100 на 100 или 500 на 500.
- Мне нужно использовать несколько потоков.
- Я не могу использовать нумерацию страниц, поскольку запрос к базе данных будет каждый раз получать разные документыоно выполняется.
Итак, после долгих раздумий, я думаю, единственное возможное решение - повторять задание, пока запрос не получит никаких документов.Это возможно?Я хочу сделать что-то вроде шага: Делайте что-то, пока не будет возвращено значение null - повторяйте задание, пока запрос не вернет ноль записей.
Если это не очень хороший подход, я буду признателен за другие возможные решения.
Спасибо.