Как объявить `@ Transactional` в сервисе Spring Boot, чтобы исключение вызывалось« немедленно »? - PullRequest
1 голос
/ 09 мая 2019

Скажите, у меня есть следующие весенние бобы в приложении весенней загрузки. Мое намерение состоит в том, чтобы сделать foo() транзакционным так:

  1. Когда barService.bar() генерирует исключения, персистент получает откат.
  2. Когда персистент вызывает исключение, исключение распространяется до вызывающей стороны «немедленно», поэтому barService.bar() НЕ вызывается .
@Service
public class FooService
{
    @Autowired
    private FooRepository fooRepository;
    @Autowired
    private BarService barService;

    @Transactional
    public void createFoo(Foo foo) {
        fooRepository.save(foo);
        // expect to not execute when the above line throws exceptions
        barService.bar();
    }
}

@Service
public class BarService {
    public void bar() {

    }
}

Пока что первое требование работает, а второе - нет. Когда персист бросает исключение, barService.bar() ВСЕГДА называется .

Если я удаляю @Transactional, 2-е требование работает, 1-е не работает.

Я также попробовал все Propagation типы, ни один из них не работает так, как я ожидал. Например, если я использую @Transactional(MANDATORY), я получаю следующую ошибку:

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

1 Ответ

3 голосов
/ 09 мая 2019

Без @Transactional каждый вызов метода репо является отдельной транзакцией, и он будет сброшен немедленно. Вот почему ваше второе требование работало без @Transactional.

Когда вы добавляете @Transactional, все createFoo() становится одной единицей транзакции. Следовательно, изменения, которые вы делаете при вызове save(), будут сброшены только тогда, когда createFoo() завершит свое выполнение. Вот почему ваше первое требование работало с @Transactional.

Чтобы достичь желаемого, оставьте @Transactional и наберите saveAndFlush() вместо save().

...