在TransactionalEventListener中删除了写调用/事务

时间:2017-05-01 19:54:16

标签: spring hibernate spring-boot kotlin spring-transactions

我正在使用带有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 

建立了一个连接的新事务,一切正常。

  1. 我不喜欢在删除此写入时日志中完全静默(再次读取成功)。是否有已知错误?

  2. 如何启用处理程序以启动新事务?如果我在handleEnqueue事件上执行Propogation.Requires_new,它就不起作用。

  3. 此外,启用成功记录读/写的log4jdbc我在spring中有以下设置。

    由于

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。事务实际上在TransactionShachronization #afterCompletion(int)的文档中提到了这种行为,它由TransactionPhase.AFTER_COMMIT(这是@TransactionalEventListener的默认TransactionPhase属性)引用:

  

事务已经提交或回滚,但事务资源可能仍然是活动的和可访问的。因此,此时触发的任何数据访问代码仍将“参与”原始事务,允许执行一些清理(不再执行任何提交!),除非它明确声明它需要在单独的事务中运行。因此:对于从此处调用的任何事务操作,请使用PROPAGATION_REQUIRES_NEW。

不幸的是,除了通过Propagation.REQUIRES_NEW强制执行新事务之外,似乎没有别的选择。问题是transactionalEventListeners实现为事务同步,因此绑定到事务。当事务关闭并且其资源被清理时,监听器也是如此。可能有一种方法可以使用自定义的EntityManager来存储事件,然后在调用close()之后发布它们。

请注意,您可以在@TransactionalEventListener上使用TransactionPhase.BEFORE_COMMIT,这将在提交事务之前进行。这会将您的更改写入数据库,但您不会知道您正在侦听的事务是实际提交还是即将回滚。