SoFunction
Updated on 2025-03-09

Detailed explanation of how to switch multiple data sources in Spring

Since it is a spring project, you can use the DataSource object of spring to manage it. The general idea is to create a class (such as MyRoutingDataSource) to implement the interface, replace the original DataSource object of spring, and manage the data sources that require spring to work through MyRoutingDataSource. What design pattern does this belong to? ?

spring jdbc has taken into account, inheriting the AbstractRoutingDataSource abstract class in spring to implement the determineCurrentLookupKey method, and the setTargetDataSources method needs to be transferred in the map form. Is it a template method design pattern? ?

Implementing multi-data source configuration and switching in the Spring framework usually involves the following steps:

1. Define the data source

Define multiple in Spring configuration file (XML or Java Config)DataSource bean。

2. Configure JPA or MyBatis

If you are using JPA, you may need to configure one for each data sourceEntityManagerFactoryandTransactionManager. If you use MyBatis, you may need to configure one for each data sourceSqlSessionFactoryandSqlSessionTemplate

3. Use@Qualifieror@Primary

When you have multiple beans of the same type, you can use@QualifierAnnotation to specify the bean to inject. Or, you can use@PrimaryAnnotation marks a data source as primary so that it is automatically injected when no explicit specification is required.

4. Implement data source routing

Data source routing is the key to implementing multi-data source switching. You can inheritAbstractRoutingDataSourceCreate a custom data source that can switch data sources based on an identifier in the current thread or request context.

5. Set up data source using AOP or interceptor

Before request processing, you can use AOP or interceptor to set the data source identifier of the current thread. This way, when the data access layer (such as a JPA repository or MyBatis Mapper) tries to get the data source, it will get the correct data source through your custom data source routing logic.

Sample code

Customize data source routing

public class DynamicDataSource extends AbstractRoutingDataSource {  
  
    @Override  
    protected Object determineCurrentLookupKey() {  
        // Here you can return different data source identifiers as needed        // For example, get the data source identifier of the current thread from ThreadLocal        return ();  
    }  
}  
  
// Tool class used to save the data source identifier of the current threadpublic class DataSourceContextHolder {  
  
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();  
  
    public static void setCurrentDataSource(String dataSource) {  
        (dataSource);  
    }  
  
    public static String getCurrentDataSource() {  
        return ();  
    }  
  
    public static void clearCurrentDataSource() {  
        ();  
    }  
}

Configure data source

@Configuration  
public class DataSourceConfig {  
  
    @Bean(name = "primaryDataSource")  
    @ConfigurationProperties(prefix = "")  
    public DataSource primaryDataSource() {  
        // ... Configure and return DataSource        return ().build(); 
    }  
  
    @Bean(name = "secondaryDataSource")  
    @ConfigurationProperties(prefix = "")  
    public DataSource secondaryDataSource() {  
        // ... Configure and return DataSource        return ().build();
    }  
  
    @Bean(name = "dataSource")  
    public DataSource dynamicDataSource() {  
        DynamicDataSource dataSource = new DynamicDataSource();  
        Map<Object, Object> targetDataSources = new HashMap<>();  
        ("primary", primaryDataSource());  
        ("secondary", secondaryDataSource());  
        (targetDataSources);  
        (primaryDataSource());  
        return dataSource;  
    }  
  
    // Configure other necessary components such as EntityManagerFactory and TransactionManager (if required)}

Set up data source using AOP or interceptor

@Aspect  
@Component  
public class DataSourceAspect {  
  
    @Pointcut("@annotation(customDataSource)")  
    public void dataSourcePointcut(CustomDataSource customDataSource) {}  
  
    @Before("dataSourcePointcut(customDataSource)")  
    public void switchDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        (());  
    }  
  
    @After("@annotation(customDataSource)")  
    public void restoreDataSource(JoinPoint joinPoint, CustomDataSource customDataSource) {  
        ();  
    }  
}  
  
// Custom annotations, used to specify data sources@Target({, })  
@Retention()  
public @interface CustomDataSource {  
  
    String value() default "primary";  
}

Now you can switch data sources using the @CustomDataSource annotation on the method you need to specify the data source. Before the method is executed, the AOP section will set the data source identifier of the current thread and clear it after the method is executed. In this way, the data access layer can obtain the correct data source through DynamicDataSource.

This is the end of this article about how to switch Spring multi-data source. For more related Spring multi-data source switching content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!