Что здесь происходит?
Транзакция автоматически откатывается, поскольку она помечена как
откатить только.
Это происходит, когда внешний метод @Transactional
вызывает внутренний метод @Transactional
, и оба имеют одинаковую физическую передачу (например, оба Propagation.REQUIRED
являются настройкой по умолчанию). Затем, когда внутренний метод генерирует исключение, он помечает TX как необходимый откат. Однако если внешний метод фиксирует TX, это исключение произойдет. Это нормальное поведение, как задумано, потому что внутренний метод говорит, что хочет выполнить откат, а внешний метод говорит, что хочет зафиксировать, что противоречит друг другу.
В вашем случае внутренний метод, имеющий @Transactional
, взят из JpaRepository#save
(Это текущий дизайн данных Spring). Если в нем происходит исключение и вы перехватываете все исключения во внешнем методе (т.е. BookingResource#createReservtion()
), это исключение происходит.
Решение
В соответствии с вашими требованиями, вы должны повторно выбросить исключение из BookingResource#createReservtion()
после того, как вы поймали исключение. Также необходимо убедиться, что для noRollbackFor
в createReservtion()
'@Transactional
не задан тип, который совпадает с переброшенным исключением, чтобы сигнализировать о том, что вы хотите выполнить откат, а не фиксировать внешний метод, что-то вроде :
@PostMapping("/booking")
@Transactional
public ResponseEntity<BookingResourceResponse> createReservtion(@RequestBody Reservation body) {
//code...
try {
int day = 0;
do {
reservationRepository.save(new Reservation(..., day));
}
while(day <= LIMIT_VALUE);
return buildResponse(HttpStatus.CREATED, new BookingResourceResponse(body));
}
catch(Exception e) {
throw new AppException(buildResponse(HttpStatus.CONFLICT, new BookingResourceResponse("Some error here")) , e);
}
}