Я хочу выйти из метода с аннотацией @Transactional, и я хочу иметь возможность передавать сообщение в пользовательский интерфейс в случае сбоя обновления/сохранения.
Существует ряд ответов, но у всех есть проблемы. Вот что я пробовал:
1. Перехват DataIntegtrityException
Этот способ создает собственное исключение. Минус в том, что он не работает с @Transactional
Код: Выделить всё
//@Transactional - doesn't catch exception with @Transactional
public CarCreateDto updateCar(CarCreateDto updateCarDto, Long id) {
Car Car = CarRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Car with " + id + " not found"));
try {
CarMapper.partialUpdate(updateCarDto, Car);
CarRepository.save(Car);
return CarMapper.toDto(Car);
} catch (DataIntegrityViolationException e) {
throw new CarAlreadyExistsException("Car with name already exist");
}
}
То же, что и выше, но использует saveAndFlush и работает с @Transactional. Не могу найти ссылку, но проблема в том, что saveAndFlush использовать нецелесообразно.
Код: Выделить всё
@Transactional
public CarCreateDto updateCar(CarCreateDto updateCarDto, Long id) {
Car Car = CarRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Car with " + id + " not found"));
try {
CarMapper.partialUpdate(updateCarDto, Car);
CarRepository.save(Car);
return CarMapper.toDto(Car);
} catch (DataIntegrityViolationException e) {
throw new CarAlreadyExistsException("Car with name already exist");
}
}
Минусом здесь является дополнительный вызов базы данных. Также возможны проблемы с параллелизмом.
Код: Выделить всё
@Transactional
public CarCreateDto updateCar(CarCreateDto updateCarDto, Long id) {
Car Car = CarRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Car with " + id + " not found"));
boolean samename = updateCarDto.getName().equalsIgnoreCase(Car.getName());
if (samename || !samename && !CarRepository.existsByName(updateCarDto.getName())) {
CarMapper.partialUpdate(updateCarDto, Car);
CarRepository.save(Car);
return CarMapper.toDto(Car);
} else {
throw new DatabaseUniqueConstraintException("Car with name " + updateCarDto.getName() + " already exists");
}
}
Это просто кажется неправильным — контроллер не несет ответственности за перехват исключений БД.
Код: Выделить всё
@PutMapping(value = "/{id}", consumes = "application/json")
ResponseEntity updateCarDto(@Valid @RequestBody CarCreateDto updateCar, @PathVariable Long id) {
System.out.println("wait");
try {
CarCreateDto Car = CarService.updateCar(updateCar, id);
return new ResponseEntity(Car, HttpStatus.OK);
} catch (DataIntegrityViolationException e) {
throw new CarAlreadyExistsException("Car with name already exist");
}
}
Подробнее здесь: https://stackoverflow.com/questions/772 ... ing-boot-3
Мобильная версия