#java #multithreading #spring-boot #java-8 #transactions
Вопрос:
У меня есть список, который содержит, скажем, 4 DTO. Я выполняю некоторые процессы над каждым из DTO, представленных в моем списке. Если предположить, что для одного DTO возникает какое-либо исключение, то все транзакции откатываются (даже если процесс завершен успешно для других 3 DTO).
Мой код выглядит так :
@Transactional
public void processEvent(List<MyObject> myList){
myList.forEach(dto -> process(dto));
}
public void process(MyObject dto){
//some code which calls another class marked as @Transactional
// and save the data processed to database
}
Я хочу выполнить эти процессы для каждого DTO в отдельном потоке, чтобы исключение, встречающееся в одном потоке, не отменяло транзакцию для всех DTO.
Также есть ли способ обрабатывать эти DTO один за другим в разных потоках, чтобы поддерживать согласованность данных ?
Комментарии:
1. Что заставляет вас думать, что этот код многопоточен? В этом коде нет ничего многопоточного. Если вам нужна новая транзакция для каждого объекта, сделайте это, создайте новую транзакцию, для этого и предназначен уровень
REQUIRES_NEW
распространения.2. @M. Deinum Я знаю, что мой код не многопоточен. Я в замешательстве, как лучше всего сделать мой код многопоточным, чтобы я получал новую транзакцию для каждого объекта (при сохранении согласованности данных) ?
3. @YashAgarwal . . . вам не нужно делать свой код многопоточным, чтобы получить новую транзакцию. Просто используйте
propagation
атрибут@Transactional
аннотации Spring, как сказал М. Дейнум. Смотрите здесь: docs.spring.io/spring-framework/docs/current/javadoc-api/org/.. .. .4. @MatheusCirillo Спасибо за разъяснение. Раньше я не был уверен в том, как справиться с этой проблемой.
Ответ №1:
Просто переместите транзакцию в метод, вызываемый с помощью dto, плюс я не уверен, нужна ли транзакция для dto. Это выглядит как контроллер, у которого не должно быть никаких транзакционных аннотаций. В сервисе, как только вы измените dto на entity и будете готовы сохранить его, вы можете поместить аннотацию. Кроме того, если вы просто вызываете метод сохранения репозитория, вам не нужно быть в транзакции, так как метод сохранения имеет аннотацию в репозитории.
public void processEvent(List<MyObject> myList){
myList.forEach(dto -> process(dto));
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void process(MyObject dto){
//some code which calls another class marked as @Transactional
// and save the data processed to database
}
И последний совет: не ставьте @Transactional на классы, за исключением случаев, когда для параметра только для чтения установлено значение true. Затем вы можете поместить @Transactional в методы, которые выполняют любые операции CRUD.