我正在使用带有hibernate(5.0.1.Final)的spring-boot(1.4.1)。我注意到当我尝试从@TransactionalEventListener
处理程序中写入数据库时,调用被简单地忽略。读取通话工作正常。
当我说忽略时,我的意思是数据库中没有写入并且没有日志。我甚至启用了log4jdbc,但仍然没有日志,这意味着没有创建hibernate会话。从此,我认为,在spring-boot的某个地方,我们确定它是一个事务事件处理程序并忽略一个写调用。
这是一个例子。
// 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我在spring中有以下设置。
由于
答案 0 :(得分:1)
我遇到了同样的问题。事务实际上在TransactionShachronization #afterCompletion(int)的文档中提到了这种行为,它由TransactionPhase.AFTER_COMMIT(这是@TransactionalEventListener的默认TransactionPhase属性)引用:
事务已经提交或回滚,但事务资源可能仍然是活动的和可访问的。因此,此时触发的任何数据访问代码仍将“参与”原始事务,允许执行一些清理(不再执行任何提交!),除非它明确声明它需要在单独的事务中运行。因此:对于从此处调用的任何事务操作,请使用PROPAGATION_REQUIRES_NEW。
不幸的是,除了通过Propagation.REQUIRES_NEW强制执行新事务之外,似乎没有别的选择。问题是transactionalEventListeners实现为事务同步,因此绑定到事务。当事务关闭并且其资源被清理时,监听器也是如此。可能有一种方法可以使用自定义的EntityManager来存储事件,然后在调用close()之后发布它们。
请注意,您可以在@TransactionalEventListener上使用TransactionPhase.BEFORE_COMMIT,这将在提交事务之前进行。这会将您的更改写入数据库,但您不会知道您正在侦听的事务是实际提交还是即将回滚。