Мне нужно обработать список элементов, и, если возникает исключение (или RuntimeException), оно не может отменить работу, выполненную ранее. Это должно только отменить операцию базы данных в это время, и другие элементы должны продолжить обрабатываться.
Моя стратегия состояла в том, чтобы создать класс с распространение = распространение. ТРЕБУЕТСЯ с для для * oop, и внутри него я бы вызвал другой метод с распространение = распространение .REQUIRES_NEW .
Transaction 1->
loop -> transaction 2
-> transaction 3
-> ...
-> transaction N
end of transaction 1
В этой стратегии, если в транзакции 2 возникнет исключение, он будет откатан и транзакция 3 продолжится в обычном режиме.
Проблема: если в транзакции 2 возникает исключение, он не откатывается и транзакция 3 продолжается в обычном режиме. На транзакцию 1 это не влияет.
Если я добавлю throw e в блоке перехвата Service2 и произойдет исключение в транзакции 3, она будет откатана, а транзакция 2 не затрагивается (пока все хорошо), но транзакция 1 получает исключение, и процесс останавливается, не обрабатывая оставшиеся элементы.
Что я делаю не так? = /
Код:
package test.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DefaultController {
@Autowired
private Service1 service1;
@ResponseBody
@RequestMapping(method = RequestMethod.GET, path = "/")
public ResponseEntity<?> test() throws Exception {
service1.m1();
return new ResponseEntity<>(HttpStatus.OK);
}
}
Этот контроллер вызывает сервис:
package test.controller;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class Service1 {
@Autowired
private Service2 service2;
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public void m1() {
List<Integer> list = Arrays.asList(1, 2);
for (Integer j : list) {
service2.m2(j);
System.out.println("Exception for j = " + j);
}
}
}
И этот сервис1 вызывает сервис2, потому что я знал, что Spring Boot AOP основан на прокси-сервере, затем мне нужен был другой компонент для переключения Распространения моих транзакций:
package test.controller;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import test.model.domain.Log;
import test.service.LogService;
@Service
public class Service2 {
@Autowired
private LogService logger;
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRES_NEW)
public void m2(int i) {
try {
Log log = new Log();
log.setDataMensagem(new Date());
log.setDescricaoEnvioRecebimento("TEST");
log.setDescricaoMensagem("TEST1");
log.setIdMensagem("TEST2");
log.setNomeFilaServico("TESTE3");
logger.save(log);
if (i == 2) {
throw new RuntimeException();
}
} catch (Exception e) {
System.out.println("RuntimeException in i = " + i);
}
}
}
LogService:
package test.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import test.indicador.LogFilaServicoIndicador;
import test.model.domain.Log;
import test.repository.LogRepository;
@Service
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public class LogService {
private final LogRepository repository;
public LogService(LogRepository repository) {
this.repository = repository;
}
public Log save(Log logFilaServico) {
return repository.save(logFilaServico);
}
}
Репозиторий:
package test.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import test.model.domain.Log;
@Repository
public interface LogRepository extends CrudRepository<Log, Long> {
}