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, но об этом там не упоминается.
По моему опыту, эти обработчики выполняются за пределами основной транзакции. Буквально «до» и «после». О «отдельной» транзакции - если вы отметите свой обработчик событий как @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 не может откатить это из-за этого. какие-либо предложения. ОК, чтобы использовать компенсационную транзакцию