写入调用/事务被丢弃在 TransactionalEventListener
Posted
技术标签:
【中文标题】写入调用/事务被丢弃在 TransactionalEventListener【英文标题】:Write call/transaction is dropped in TransactionalEventListener 【发布时间】:2017-09-29 05:57:32 【问题描述】:我正在使用 spring-boot(1.4.1) 和 hibernate(5.0.1.Final)。我注意到,当我尝试从 @TransactionalEventListener
处理程序中写入数据库时,调用被简单地忽略了。读取调用工作得很好。
当我说忽略时,我的意思是数据库中没有写入,也没有日志。我什至启用了 log4jdbc,但仍然没有日志,这意味着没有创建休眠会话。据此,我认为,在 spring-boot 的某个地方,我们确定它是一个事务事件处理程序并忽略了一个 write 调用。
这是一个例子。
// This function is defined in a class marked with @Service
@TransactionalEventListener
open fun handleEnqueue(event: EnqueueEvent)
// some code to obtain encodeJobId
this.uploadService.saveUploadEntity(uploadEntity, encodeJobId)
@Service
@Transactional
class UploadService
//.....code
open fun saveUploadEntity(uploadEntity: UploadEntity, encodeJobId: String): UploadEntity
// some code
return this.save(uploadEntity)
现在,如果我通过注释来强制执行新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
saveUploadEntity
建立了一个新的连接事务,一切正常。
我不喜欢在删除此写入时日志中完全静默(再次读取成功)。是否存在已知错误?
如何启用处理程序来启动新事务?如果我对我的 handleEnqueue 事件执行 Propogation.Requires_new,它就不起作用。
此外,启用 log4jdbc 成功记录读/写我在春天有以下设置。
谢谢
【问题讨论】:
【参考方案1】:我遇到了同样的问题。这种行为实际上是在 TransactionSynchronization#afterCompletion(int) 的文档中提到的,它由 TransactionPhase.AFTER_COMMIT(这是 @TransactionalEventListener 的默认 TransactionPhase 属性)引用:
事务将已提交或回滚,但事务资源可能仍处于活动状态且可访问。因此,此时触发的任何数据访问代码仍将“参与”原始事务,允许执行一些清理(不再有提交!),除非它明确声明它需要在单独的事务中运行。因此:对从这里调用的任何事务操作使用 PROPAGATION_REQUIRES_NEW。
不幸的是,这似乎除了通过 Propagation.REQUIRES_NEW 强制执行新事务之外别无选择。问题是 transactionalEventListener 被实现为事务同步,因此绑定到事务。当事务关闭并且其资源被清理时,侦听器也是如此。可能有一种方法可以使用自定义的 EntityManager 存储事件,然后在调用其 close() 后发布它们。
请注意,您可以在 @TransactionalEventListener 上使用 TransactionPhase.BEFORE_COMMIT,这将在事务提交之前发生。这会将您的更改写入数据库,但您不知道您正在侦听的事务是实际提交还是即将回滚。
【讨论】:
以上是关于写入调用/事务被丢弃在 TransactionalEventListener的主要内容,如果未能解决你的问题,请参考以下文章
Spring中同一个service中方法相互调用事务不生效问题解决方案
从另一个方法调用的@Transactional 方法没有获得事务
spring @Transactional 传播机制(参数 propagation )
Spring——事务注解@Transactional建议收藏
SpringBoot设置 @Transactional ,并在异常处理中调用setRollbackOnly()事务不回滚