问题
Spring Data REST has the following Event handlers which are fired on HTTP requests like POST, PUT etc.
@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 ....");
}
}
My question is if I access another database entity, eg.Book, within @HandleBeforeCreate and modify it, would it occur in a separate transaction or will it occur in the same transaction as the creation of the Author entity?
I already check the Spring Data REST docs but it is not mentioned there.
回答1:
From my experience, those handlers are performed beyond the main transaction. Literally 'before' and 'after' it. About 'separate' transaction - if you mark your event handler as @Transactional
it will be executed in its individual transaction.
Publishing domain events from the aggregate root
If you need to perform some extra actions within the main transaction you can use publishing events from the aggregate root. In this case, you should extend your entity from AbstractAggregateRoot and add to it some methods that register appropriate events, for example:
@Entity
public class Model extends AbstractAggregateRoot {
// entity stuff...
public Model initExtraAction(SomeData payload) {
registerEvent(new ExtraActionEvent(this, payload));
return this;
}
}
where registerEvent is the AbstractAggregateRoot
method, and ExtraActionEvent
is your custom event, like the folowing:
@Value
public class ExtraActionEvent {
private Model model;
private SomeData payload;
}
Then you can implement an ordinary event handler
@Service
public class EventHandler {
@EventListener
@Transactional(propagation = MANDATORY) // optional
public void handleExtraActionEvent (ExtraActionEvent e) {
Model model = e.getModel();
SomeData payload = e.getPayload();
// Extra actions...
}
}
that will be called in the same transaction as the main one (which saves your entity) if you call initExtendAction
method before invoking the save
method of your repo (to make sure that this will be done in the same transaction you can use an optional @Transactional(propagation = MANDATORY)
annotation):
modelRepo.save(model.initExtraAction(payload));
In the Spring Data REST project we can call initExtraAction
method in the 'RepositoryEventHandler' before the entity will be created or updated:
@RepositoryEventHandler(Model.class)
public class ModelEventHandler {
@HandleBeforeCreate
@HandleBeforeSave
public void handleBeforeCreateOrSave(Model model){
// Some manipulations...
model.initExtraAction(...);
}
}
You can find a full example of using AbstractAggregateRoot
in the Oliver Gierke Spring RestBucks demo project.
Additional info: DDD Aggregates and @DomainEvents
来源:https://stackoverflow.com/questions/52241626/does-spring-data-rest-event-hanlders-use-separate-database-transactions