Does Spring Data REST event hanlders use separate database transactions?

这一生的挚爱 提交于 2020-03-05 06:06:54

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!