簡體   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