解决 Spring Boot 多数据源环境下事务管理器冲突问题(非Neo4j请求标记了 @Transactional 尝试启动Neo4j的事务管理器)-4. 解决方案

时间:2025-04-20 08:49:16

决定继续使用 dynamic-datasource-spring-boot-starter 以保留其灵活性,并通过 Java 配置显式定义主事务管理器。

在 对应工程的对应目录下新增(或者修改对应的)一个配置类 DataSourceConfig.java :

package com.xxx.xxxx.config; // 使用项目实际的包路径

import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class DataSourceConfig {

    /**
     * 显式定义与动态数据源关联的事务管理器。
     * @param dataSource Spring 容器会自动注入由 dynamic-datasource-spring-boot-starter 创建的代理 DataSource Bean。
     *                   这个代理 DataSource 知道如何根据上下文切换到 dsPrimary 或其他数据源。
     * @return 标记为 @Primary 的事务管理器
     */
    @Bean("transactionManager") // 使用标准的 "transactionManager" 作为 Bean 名称
    @Primary // <--- 关键:标记为主要事务管理器
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        // 使用注入的动态数据源代理来创建事务管理器
        return new DataSourceTransactionManager(dataSource);
    }
}

实施效果:

添加此配置类后,Spring 容器中存在三个 PlatformTransactionManager Bean:

  • devTransactionManager (Neo4j)
  • prodTransactionManager (Neo4j)
  • transactionManager (Oracle, 使用动态数据源代理, @Primary )

当调用仅涉及 Oracle 且标记了 @Transactional 的 API 时,Spring 会自动选用被 @Primary 标记的 transactionManager ,不再尝试使用 Neo4j 的事务管理器,也解决了 NoUniqueBeanDefinitionException 。应用程序在 Neo4j 宕机时,涉及 Oracle 的 API 可以正常工作。