Spring Data Jpa - репозиторий не генерирует исключение, когда существует @transactional

У меня есть следующие классы:

public interface GarageRepository extends PagingAndSortingRepository<Garage, Integer> {}

public class GarageBO {
  private GarageRepository garageRepository;

  public void updateGarage(Garage garage) {
    try {
      garageRepository.save(garage);
    } catch (Exception e) {
      throw BoozinaExceptions.getCodeException(garage, e);
    }
  }
}

public class GarageFacade implements GarageService {
  private GarageBO garageBO;

  @Transactional
  public void updateGarage(Garage garage) {
    garageBO.updateGarage(garage);
  }
}

Предположим, что я пытаюсь обновить гараж, и возникает уникальное нарушение.
Когда я вызываю updateGarage из GarageFacade с аннотацией @Transactional, гаражный репозиторий не выдает никаких исключений.
Когда я вызываю тот же метод без @Transactional аннотация, GarageRepository выдает уникальное исключение нарушения, и теперь я могу преобразовать исключение, используя BoozinaExceptions.getCodeException(garage, e);

Такое поведение происходит потому, что когда у меня есть аннотация @Transactional, исключение будет выдано, когда данные Spring jpa выполнят фиксацию. Это происходит после выполнения GarageBO.updateGarage.

Но мне нужно преобразовать уникальное нарушение. Как я могу это сделать?
Как обработать исключение spring после фиксации, а затем преобразовать в мое исключение?


person Sandro Simas    schedule 23.02.2014    source источник
comment
Когда объект гаража не существует и я пытаюсь его сохранить, выполняется блок catch, и я могу преобразовать исключение. Но когда объект гаража уже существует, блок catch не выполняется, и в журнале гибернации появляется эта строка: HHH000010: при выпуске пакета он все еще содержал операторы JDBC.   -  person Sandro Simas    schedule 23.02.2014


Ответы (1)


То, что вы описываете, является ожидаемым поведением. Транзакция фиксируется после завершения метода, фиксация приводит к нарушению ограничения уникальности.

Добавление @Transactional к методам службы приводит к завершению транзакции после вызова метода службы, когда транзакция фиксируется. Его удаление приводит к фиксации транзакции после вызова метода репозитория.

Кроме того, почему у вас есть БО Фасад и Репозиторий?! В принципе БО и Фасад одно и то же ИМХО.

ЧТОБЫ решить вашу проблему, GarageRepository расширьте JpaRepository вместо PagingAndSortingRepository и вызовите метод saveAndFlush вместо save. Это выполнит sql (без фиксации транзакции) и вызовет исключение нарушения ограничения.

Другое решение состоит в том, чтобы вместо выполнения try/catch в вашем BO создать и Aspect, который выполняет преобразование. Избавляет вас от написания кода try/catch каждый раз, когда вам это нужно.

person M. Deinum    schedule 23.02.2014
comment
У меня есть BO и Facabe, потому что фасад может взаимодействовать с более чем одним объектом BO. Пример: GarageFacade имеет GarageBO и MessageBO, потому что, когда я создаю Garage, я создаю сущность Garage и отправляю электронное письмо с MessageBO. Но я также могу создать гараж без отправки электронной почты или я могу отправить электронную почту без создания гаража. - person Sandro Simas; 24.02.2014