Почему мой Spring @EventListener показывает другое поведение транзакций при отправке событий, чем при непосредственном вызове? - PullRequest
0 голосов
/ 03 мая 2019

При использовании функциональности @EventListener с репозиториями Spring Data поведение отличается от того, когда вызывается один и тот же процедурный код.

Мои постоянные объекты публикуют события, используя следующий базовый класс:

  public abstract class Aggregate  {

      @Transient
      private transient final Set<Object> events = new LinkedHashSet<>();

      protected <T> T registerEvent(T event) {
          this.events.add(event);
          return event;
      }

      @DomainEvents
      Collection<Object> events() {
          return Collections.unmodifiableSet(events);
      }

      @AfterDomainEventPublication
      void clearEvents() {
          this.events.clear();
      }
  }

Мой класс прослушивания событий реализован следующим образом:

  class Service {

      @EventListener
      public void listener(SomeEvent event) {
          someOtherRepository.save(someOtherPersistentObject);
          someOtherCode();
      }
  }

Когда прослушиватель запускается и метод someOtherRepository save(…) не удается, будет выполнен откат.Но someOtherCode() выполняется независимо от отката.

Но когда я удаляю все функции @EventListening и вызываю метод listener(…) сразу после точки, в которой исходный репозиторий отвечает за запуск события.Тогда я получаю другое поведение.Тогда someOtherCode() никогда не выполняется, а метод someOtherRepository.save(…) немедленно завершается сбоем.

Исходная служба, ответственная за публикацию события, выглядит следующим образом

public OriginatingService {
    @Transactional
    public void someMethod() {
        originatingRepoDifferentFromSomeOtherRepo.save(something);

Почему это происходит и существует лиспособ заставить то же поведение на моей реализации прослушивания событий?

1 Ответ

2 голосов
/ 03 мая 2019

Поскольку запись в базу данных может быть отложена до фиксации транзакции, т.е. когда возвращается транзакционный метод.

Обновите, как показано ниже, для явного запуска немедленного сброса:

 @EventListener
  public void listener(SomeEvent event) {
      someOtherRepository.saveAndFlush(someOtherPersistentObject);
      someOtherCode();
  }
...