繁体   English   中英

事务,Spring Boot Starter JDBC & R2DBC

[英]Transactions, Spring Boot Starter JDBC & R2DBC

我正在尝试将使用 JDBC 模板的 Spring Boot 项目版本 2.3.0.M3 迁移到 R2DBC。 该项目还使用 Liquibase,因此我无法完全摆脱 JDBC。 我在项目中同时拥有 spring-boot-starter-data-r2dbc 和 spring-boot-starter-jdbc 依赖项,在尝试运行其中一项测试时出现以下异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: transactionManager,connectionFactoryTransactionManager

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1180)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:416)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:480)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:335)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
...

bean connectionFactoryTransaction 管理器在 Spring 类 R2dbcTransactionManagerAutoConfiguration 中定义如下:

    @Bean
    @ConditionalOnMissingBean(ReactiveTransactionManager.class)
    public R2dbcTransactionManager connectionFactoryTransactionManager(ConnectionFactory connectionFactory) {
        return new R2dbcTransactionManager(connectionFactory);
    }

bean transactionManager 在 Spring 类 DataSourceTransactionManagerAutoConfiguration 中是这样定义的:

   @Bean
   @ConditionalOnMissingBean(PlatformTransactionManager.class)
   DataSourceTransactionManager transactionManager(DataSource dataSource,
           ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
       DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
       transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
       return transactionManager;
   }

可以看出,@ConditionalOnMissingBean 注释包含不同的类型,这将导致创建两个 bean 的实例。 但是,在 Spring 类 TransactionAspectSupport 中,determineTransactionManager 方法中有这行代码:

defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);

由于事务管理器类型DataSourceTransactionManager 和R2dbcTransactionManager 都实现了TransactionManager 接口,因此上面的两个事务管理器bean 都会匹配,并且会发生错误。

我现在正在联系是否有人设法解决或解决了这个问题?
提前致谢!

受 M. Deinums 回答的启发(谢谢!),我将以下步骤应用于我的项目,之前失败的测试现在成功运行:

  • 删除 spring-boot-starter-jdbc 依赖项。
  • 向 spring-jdbc 添加依赖项。
  • 添加对 HikariCP (com.zaxxer) 的依赖。
  • 添加 spring.liquibase 用户和密码属性(我已经有了 url 和更改日志属性)。
  • 删除所有 spring.datasource 属性(我有 url 和 drive-class-name)。

我定义了 spring.r2dbc 属性用户名、密码和 url,我不需要更改。

更新:
另外,我在测试中使用了Testcontainers,无法分配静态端口。 为了能够在 Liquibase 上配置数据库端口,我覆盖了一个类型为 SpringLiquibase 的 bean 名称 liquibase 并在 liquibase bean 创建方法中创建了一个 DataSource(不公开为 bean)并将其设置在 liquibase bean 上。

spring-boot-starter-jdbcspring-boot-starter-data-r2dbc共存。 有一个类org.springframework.transaction.annotation.TransactionManagementConfigurer可用于解决冲突。 当 r2dbc 存在时,Spring Boot 2.3.0 似乎禁用了自动数据源配置。 可以手动导入org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration类以使两者共存。

@Bean
TransactionManagementConfigurer transactionManagementConfigurer(ReactiveTransactionManager reactiveTransactionManager) {
    return new TransactionManagementConfigurer() {
        @Override
        public TransactionManager annotationDrivenTransactionManager() {
            return reactiveTransactionManager;
        }
    };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM