Используют ли обработчики событий Spring Data REST отдельные транзакции базы данных?

Spring Data REST имеет следующие обработчики событий, которые запускаются по HTTP-запросам, таким как POST, PUT и т. д.

@RepositoryEventHandler(Author.class) 
public class AuthorEventHandler {
    Logger logger = Logger.getLogger("Class AuthorEventHandler");

    @HandleBeforeCreate
    public void handleAuthorBeforeCreate(Author author){
        logger.info("Inside Author Before Create....");

    }

    @HandleAfterCreate
    public void handleAuthorAfterCreate(Author author){
        logger.info("Inside Author After Create ....");

    }

}

У меня вопрос: если я получу доступ к другому объекту базы данных, например, Book, в @HandleBeforeCreate и изменю его, произойдет ли это в отдельной транзакции или это произойдет в той же транзакции, что и создание объекта Author?

Я уже проверял документы Spring Data REST, но об этом там не упоминается.

2
0
1 243
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По моему опыту, эти обработчики выполняются за пределами основной транзакции. Буквально «до» и «после». О «отдельной» транзакции - если вы отметите свой обработчик событий как @Transactional, он будет выполнен в отдельной транзакции.


Публикация событий домена из агрегированного корня

Если вам нужно выполнить какие-то дополнительные действия в рамках основной транзакции, вы можете использовать публикация событий из совокупного корня. В этом случае вы должны расширить свою сущность из АннотацияАгрегатКорень и добавить к ней некоторые методы, регистрирующие соответствующие события, например:

@Entity
public class Model extends AbstractAggregateRoot {

   // entity stuff...

   public Model initExtraAction(SomeData payload) {
        registerEvent(new ExtraActionEvent(this, payload));
        return this;
   }
}

где registerEvent - это метод AbstractAggregateRoot, а ExtraActionEvent - ваше настраиваемое событие, например следующее:

@Value
public class ExtraActionEvent {
    private Model model;
    private SomeData payload;
}

Затем вы можете реализовать обычный обработчик событий

@Service
public class EventHandler {

    @EventListener
    @Transactional(propagation = MANDATORY) // optional 
    public void handleExtraActionEvent (ExtraActionEvent e) {
        Model model = e.getModel();
        SomeData payload = e.getPayload();

        // Extra actions...
    }
}

который будет вызываться в транзакции тем же как основной (который сохраняет вашу сущность), если вы вызовете метод initExtendActionдо, вызывая метод save вашего репо (чтобы убедиться, что это будет сделано в той же транзакции, вы можете использовать по желанию@Transactional(propagation = MANDATORY) аннотация):

modelRepo.save(model.initExtraAction(payload));

В проекте Spring Data REST мы можем вызвать метод initExtraAction в RepositoryEventHandler до того, как сущность будет создана или обновлена:

@RepositoryEventHandler(Model.class) 
public class ModelEventHandler {

    @HandleBeforeCreate
    @HandleBeforeSave
    public void handleBeforeCreateOrSave(Model model){
        // Some manipulations...
        model.initExtraAction(...);
    }
}

Вы можете найти полный пример использования AbstractAggregateRoot в демонстрационном проекте Oliver Gierke Весенний отдых.

Дополнительная информация: Агрегаты DDD и @DomainEvents

Привет @ Cepr0, у меня аналогичная проблема, я обновляю 2 объекта из одной транзакции (ABC и PQR). Транзакция ABC будет обновлена ​​из события, а PQR будет обновлен в аннотированном методе HandleAfterSave. Мне нужно откатить 1-ю транзакцию (обновление ABC), если 2-я транзакция не удалась (обновление PQR). Transactional здесь не работает, и я думаю, это потому, что первая транзакция выполняется через событие RepositoryEventHandler и выполняется с использованием отдельного потока. И метод HandleAfterSave не может откатить это из-за этого. какие-либо предложения. ОК, чтобы использовать компенсационную транзакцию

Sameera Manorathna 26.03.2020 19:32

Другие вопросы по теме