以@EventListener 或@TransactionalEventListener 的方法保存数据

vic*_*vic 5 spring

根据文章Better application events in Spring Framework 4.2,我设置了所有相关类。我的大部分代码都可以正常工作,但在侦听器的方法中出现异常。

控制器:

@PostMapping("/Foos")
public ResponseEntity<Foo> handle(@RequestBody Foo foo){
    Optional<Foo> f = fooService.save(foo);
    return f.isPresent() ?  new ResponseEntity<>(f, HttpStatus.OK) :
            new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
Run Code Online (Sandbox Code Playgroud)

服务:

@Transactional
public Optional<Foo> save(Foo foo){
    foo = fooRepository.save(foo);
    publisher.publishEvent(new FooEvent(foo));
    return Optional.of(foo);
}
Run Code Online (Sandbox Code Playgroud)

上面的方法没有@Transcational,下面的方法不会被触发。

聆听者

@Async
@TransactionalEventListener(condition ="#event.ok", phase = TransactionPhase.AFTER_COMMIT)
public void handle(FooEvent event){
    Product product = new Product(event.getData());
    productService.save(product);
}
Run Code Online (Sandbox Code Playgroud)

产品服务

@Transactional(propagation = Propagation.REQUIRES_NEW)
public Optional<Product> save(Product product){
    product = productRepository.save(product);
    return Optional.of(product);
}
Run Code Online (Sandbox Code Playgroud)

尽管调用了侦听器方法,但根本不会保存 Product 数据。代码在 Spring Boot 应用程序中运行 BTW。我还没有在网上找到任何相关信息。如何解决这个问题呢?

Boh*_*nko 6

根据您要实现的目标,解决方案可能会有所不同:

  1. 如果您想将产品保存在现有交易的范围内(您发布事件的地方),那么只需将阶段更改为TransactionPhase.BEFORE_COMMIT,您应该会很好。

  2. 如果您想在前一个之后的独立事务中保存产品,则将 a 添加@Transactional(propagation = Propagation.REQUIRES_NEW)到您的句柄方法并保留其他所有内容。