首页 > 解决方案 > @Transactional 在带有自定义事务管理器的 Spring Boot 中不起作用

问题描述

我正在尝试编写自己的自定义 PlatformTransactionManager 来使用 Neo4J(注意 - 由于各种原因,我不想使用 OGM,这意味着不使用 Spring Data)。

我编写了一个非常简单的 Neo4jTransactionManager 并将其添加到我的上下文中,以及 @EnableTransactionManagement 注释,然后将 @Transactonal 添加到我的运行状况检查中 - 它没有触发任何东西。

代码如下:(注 - Neo4jOperations 是 Driver 的一个包装器,使调用数据库更容易,类似于 JdbcOperations)

class Neo4jTransactionManager(private val driver: Driver) : AbstractPlatformTransactionManager() {
    companion object {
        private val LOG = LoggerFactory.getLogger(Neo4jTransactionManager::class.java)
    }

    class Neo4jTransaction(private val driver: Driver) {
        var session: Session? = null
        var transaction: Transaction? = null

        fun start() {
            if (session != null) {
                throw CannotCreateTransactionException("Transaction already started")
            }

            session = driver.session()
            transaction = session?.beginTransaction()
        }
    }

    override fun doCommit(status: DefaultTransactionStatus) {
        val transaction = unwrapTransaction(status)
        LOG.debug("Committing transaction: {}", transaction)

        if (transaction.transaction == null) {
            throw NoTransactionException("No current transaction")
        }
        transaction.transaction?.success()
        transaction.transaction?.close()
        transaction.session?.close()
    }

    override fun doBegin(transaction: Any, definition: TransactionDefinition) {
        (transaction as Neo4jTransaction).start()
    }

    override fun doGetTransaction(): Any {
        return Neo4jTransaction(driver)
    }

    override fun doRollback(status: DefaultTransactionStatus) {
        val transaction = unwrapTransaction(status)
        LOG.debug("Rolling back transaction: {}", transaction)

        if (transaction.transaction == null) {
            throw NoTransactionException("No current transaction")
        }
        transaction.transaction?.failure()
        transaction.transaction?.close()
        transaction.session?.close()
    }

    private fun unwrapTransaction(status: DefaultTransactionStatus) : Neo4jTransaction {
        return status.transaction as Neo4jTransaction
    }
}

@Configuration
@EnableTransactionManagement(proxyTargetClass = true, mode = AdviceMode.PROXY)
class DatabaseConfig {
.....
    @Bean("transactionManager")
    fun neo4jTransactionManager(driver: Driver) = Neo4jTransactionManager(driver)

    @Bean
    fun neo4jHealthcheck(neo4jOperations: Neo4jOperations) = Neo4jHealthcheck(neo4jOperations)

}

@Transactional
class Neo4jHealthcheck(private val neo4jOperations: Neo4jOperations) : AbstractHealthIndicator() {
    companion object {
        private const val QUERY = "MATCH (n) RETURN count(*) as count"
    }

    @Transactional
    override fun doHealthCheck(builder: Health.Builder) {
        val count = neo4jOperations.queryOne(QUERY).get("count").asInt()

        builder.up()
                .withDetail("Nodes", count)
                .build()
    }
}

我希望看到我的运行状况检查在事务内容周围发出一些日志消息,并在调试时在堆栈跟踪中看到它们。但我没有看到任何这些,所以它几乎就好像它完全忽略了我的 @Transactional 注释。

我错过了什么?

干杯

标签: javaspringspring-bootkotlinspring-transactions

解决方案


正如我所见,Neo4jHealthcheck 不是弹簧组件。所以可能没有创建代理。

您必须将 @Component 或任何子类型添加到 Neo4jHealthcheck

看一个带有执行器和事务的示例:

https://github.com/simasch/actuator-transactional


推荐阅读