SoFunction
Updated on 2025-04-22

SpringBoot Multi-Data Source Configuration Complete Guide

1. Basic multi-data source configuration

1. Add dependencies

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Or use other database drivers -->

2. Configure multiple data sources

#Main Data Source=jdbc:mysql://localhost:3306/db1
=root
=123456
-class-name=

#Sub-data source=jdbc:mysql://localhost:3306/db2
=root
=123456
-class-name=

3. Configure the data source bean

@Configuration
public class DataSourceConfig {

    // Master data source    @Bean
    @Primary
    @ConfigurationProperties(prefix="")
    public DataSource primaryDataSource() {
        return ().build();
    }

    // Sub-data source    @Bean
    @ConfigurationProperties(prefix="")
    public DataSource secondaryDataSource() {
        return ().build();
    }
}

2. JPA multi-data source configuration

1. Configure the main data source JPA

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = "",
    entityManagerFactoryRef = "primaryEntityManagerFactory",
    transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryJpaConfig {
    
    @Autowired @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;
    
    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        return builder
            .dataSource(primaryDataSource)
            .packages("")
            .persistenceUnit("primaryPersistenceUnit")
            .properties(jpaProperties())
            .build();
    }
    
    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        ("hibernate.", "update");
        ("", ".MySQL8Dialect");
        return props;
    }
    
    @Primary
    @Bean
    public PlatformTransactionManager primaryTransactionManager(
            @Qualifier("primaryEntityManagerFactory") EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

2. Configure the secondary data source JPA

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = "",
    entityManagerFactoryRef = "secondaryEntityManagerFactory",
    transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryJpaConfig {
    
    @Autowired @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
    
    @Bean
    public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        return builder
            .dataSource(secondaryDataSource)
            .packages("")
            .persistenceUnit("secondaryPersistenceUnit")
            .properties(jpaProperties())
            .build();
    }
    
    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        ("hibernate.", "update");
        ("", ".MySQL8Dialect");
        return props;
    }
    
    @Bean
    public PlatformTransactionManager secondaryTransactionManager(
            @Qualifier("secondaryEntityManagerFactory") EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

3. MyBatis multi-data source configuration

1. Master data source configuration

@Configuration
@MapperScan(
    basePackages = "",
    sqlSessionFactoryRef = "primarySqlSessionFactory"
)
public class PrimaryMyBatisConfig {

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "")
    public DataSource primaryDataSource() {
        return ().build();
    }

    @Primary
    @Bean
    public SqlSessionFactory primarySqlSessionFactory(
            @Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        (dataSource);
        (
            new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/primary/*.xml"));
        return ();
    }

    @Primary
    @Bean
    public SqlSessionTemplate primarySqlSessionTemplate(
            @Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

2. Sub-data source configuration

@Configuration
@MapperScan(
    basePackages = "",
    sqlSessionFactoryRef = "secondarySqlSessionFactory"
)
public class SecondaryMyBatisConfig {

    @Bean
    @ConfigurationProperties(prefix = "")
    public DataSource secondaryDataSource() {
        return ().build();
    }

    @Bean
    public SqlSessionFactory secondarySqlSessionFactory(
            @Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        (dataSource);
        (
            new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/secondary/*.xml"));
        return ();
    }

    @Bean
    public SqlSessionTemplate secondarySqlSessionTemplate(
            @Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

4. Dynamic data source configuration (runtime switching)

1. Abstract routing data source

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return ();
    }
}

2. Data source context holder

public class DataSourceContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSourceType(String dataSourceType) {
        (dataSourceType);
    }

    public static String getDataSourceType() {
        return ();
    }

    public static void clearDataSourceType() {
        ();
    }
}

3. Configure dynamic data sources

@Configuration
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix="")
    public DataSource primaryDataSource() {
        return ().build();
    }

    @Bean
    @ConfigurationProperties(prefix="")
    public DataSource secondaryDataSource() {
        return ().build();
    }

    @Primary
    @Bean
    public DataSource dynamicDataSource(
            @Qualifier("primaryDataSource") DataSource primaryDataSource,
            @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        ("primary", primaryDataSource);
        ("secondary", secondaryDataSource);
        
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        (targetDataSources);
        (primaryDataSource);
        
        return dynamicDataSource;
    }
}

4. Use AOP to switch data sources

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation()")
    public void dataSourcePointCut() {}

    @Before("dataSourcePointCut()")
    public void before(JoinPoint point) {
        MethodSignature signature = (MethodSignature) ();
        Method method = ();
        TargetDataSource ds = ();
        
        if (ds == null) {
            ("primary");
        } else {
            (());
        }
    }

    @After("dataSourcePointCut()")
    public void after(JoinPoint point) {
        ();
    }
}

5. Custom annotations

@Target({, })
@Retention()
@Documented
public @interface TargetDataSource {
    String value() default "primary";
}

6. Use examples

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    
    // Use the primary data source    public User getPrimaryUser(Long id) {
        return (id);
    }
    
    // Use data source    @TargetDataSource("secondary")
    public User getSecondaryUser(Long id) {
        return (id);
    }
}

5. Multi-data source transaction management

1. JTA distributed transactions (Atomikos)

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2. Configure JTA data source

#Main Data Source-resource-name=primaryDS
-data-source-class-name=
=jdbc:mysql://localhost:3306/db1
=root
=123456

#Sub-data source-resource-name=secondaryDS
-data-source-class-name=
=jdbc:mysql://localhost:3306/db2
=root
=123456

3. Using distributed transactions

@Service
public class OrderService {

    @Transactional // Cross-data source transactions    public void placeOrder(Order order) {
        // Operate the main data source        (order);
        
        // Operation data source        (order);
        
        // If an exception is thrown here, both operations will roll back    }
}

6. Best Practices

  1. Naming Specifications

    • Use clear naming for each data source (such as customerDS, orderDS)
    • Package structure is separated by data source (/.secondary)
  2. Connection pool configuration

-pool-size=10
-pool-size=5
  1. Monitoring indicators

    • Configure independent monitoring for each data source
    • Expose data source health metrics using Spring Actuator
  2. Performance considerations

    • High-frequency accessed data sources use larger connection pools
    • Read and write separation scenarios consider master-slave data sources
  3. Testing strategies

    • Write independent test classes for each data source
    • Test rollback behavior across data source transactions

7. Frequently Asked Questions

Question 1: Circular Dependency

// Solution: Use @DependsOn@Bean
@DependsOn("dynamicDataSource")
public PlatformTransactionManager transactionManager() {
    return new DataSourceTransactionManager(dynamicDataSource());
}

Question 2: MyBatis cache conflict

// Solution: Configure an independent cache environment for each SqlSessionFactory(configuration);
(new Environment(
    "primaryEnv", 
    transactionFactory, 
    dataSource
));

Question 3: Transaction propagation behavior abnormal

// Solution: specify the transaction manager explicitly@Transactional(transactionManager = "primaryTransactionManager")
public void primaryOperation() {...}

Through the above configuration, Spring Boot applications can flexibly support multi-data source scenarios, whether it is simple multi-store connection or complex dynamic data source switching requirements. Choose the most suitable configuration method according to the actual business scenario, and pay attention to transaction management and performance tuning.

The above is the detailed content of the complete guide to configuration of SpringBoot multi-data source. For more information about configuration of SpringBoot multi-data source, please pay attention to my other related articles!