Как избежать исключения OptimisticLockingFailureException в многопоточном репозитории

#spring-data-jpa #spring-data #spring-batch

#весна-данные-jpa #весна-данные #пружинная партия

Вопрос:

Причина первоначального исключения заключается в том, что

o.h.engine.jdbc.spi.SqlExceptionHelper: ОШИБКА: повторяющееся значение ключа нарушает уникальное ограничение «sales_update_request_pkey»

После этого,

исключение org.springframework.dao.OptimisticLockingFailureException: Попытка обновить идентификатор выполнения шага = 3185 с неверной версией (281), где текущая версия 284

Очевидно, это произошло из-за режима многопоточности. Так как в однопоточном режиме все работает так, как должно.

После этого выполнение задания останавливается, а сам шаг, на котором произошла ошибка, помечается в репозитории со статусом Сбой.

Как правильно обработать такую ошибку, чтобы выполнение работы не останавливалось.

Конфигурация шага:

 @Bean(name = "createSalesQueueStep")  public Step createSalesQueueStep() {  return stepBuilderFactory.get("createSalesQueueStep")  .lt;SalesRequest, SalesRequestgt;chunk(batchParameters.getPageSize())  .reader(salesRequestReader)  .writer(salesRequestWriter)  .faultTolerant()  .skipLimit(batchParameters.getSkipLimit())  .skip(Exception.class)  .taskExecutor(taskExecutor)  .build();  }   @Bean  public TaskExecutor taskExecutor() {  ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();  taskExecutor.setCorePoolSize(batchParameters.getPull());  taskExecutor.setMaxPoolSize(batchParameters.getPull());  taskExecutor.setWaitForTasksToCompleteOnShutdown(true);  taskExecutor.initialize();  return taskExecutor;  }  @StepScope @Component public class SalesRequestReader extends RepositoryItemReaderlt;SalesRequestgt; {   public SalesRequestReader(SalesRequestRepository salesRequestRepository,  BatchParameters batchParameters) {  super();  this.setSaveState(false);  this.setRepository(salesRequestRepository);  this.setMethodName("getSalesRequests");  this.setPageSize(batchParameters.getPageSize());  final Maplt;String, Sort.Directiongt; sorts = new HashMaplt;gt;();  sorts.put(SalesRequest_.PRODUCT_CODE, Sort.Direction.ASC);  this.setSort(sorts);  } }  @StepScope @Component @RequiredArgsConstructor public class SalesRequestWriter implements ItemWriterlt;SalesRequestgt; {   private final SalesRequestRepository salesRequestRepository;   @Override  public void write(Listlt;? extends SalesRequestgt; requests) throws Exception {  salesRequestRepository.saveAll(requests);  } }  

Может быть, существует более оптимальный (правильный подход) многопоточное пошаговое выполнение?

Комментарии:

1. Вы пробовали завернуть своего читателя в SynchronizedItemStreamReader ?