SoFunction
Updated on 2025-04-13

SpringBoot uses dynamic-datasource-spring-boot-starter to solve multi-data source problems

summary

If you want to implement a multi-tenant platform in your spare time, you need to implement data separation, dynamic configuration to generate data sources, and build a simple solution based on your own feelings.

dynamic-datasource-spring-boot-starter is a tool used to implement dynamic data source switching in Spring Boot projects. This tool mainly uses this tool to create databases and generate database connections during system operation.

Overall architecture concept

[Create a data source] Use the createDataSource method under the DefaultDataSourceCreator class to create a data source.

[Storage Data Source] Use the addDataSource method of the DynamicRoutingDataSource method to store the data source in key-value pairs.

[Switch data source] Use the **@DS** annotation to dynamically switch the data source.

Operation steps

Create a data source

The method of creating a data source is roughly as follows, mainly to create the parameter configuration of the database, so that the generator can generate a data source.

        //By default, use Mysql8.0 and connect to the mysql database table to create new database data through this connection        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        // Data source parameter configuration        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        //Fixed use of mysql8        String dbClassType = "";
        String dbUrl = ("jdbc:mysql://%s:%s/%s?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8", dbIp, dbPort, dbName);
        // Use IP to distinguish        (dbIp);
        (userName);
        (passWord);
        (dbUrl);
        (dbClassType);
        // All data sources are lazy to load, avoid declaring too many connections at once        (true);
        // Generate data source        DataSource dataSource = (dataSourceProperty);
		//Finally store it in ds, and you can use a different key to connect to different data sources later.		(dbIp,dataSource);

Later, when calling different databases, you only need to use the **@DS** annotation, the code is as follows:

    /**
      * Call different data connections to generate a new database
      * @param onlySignIp
      * @param dbName
      * @return
      */
    @DS(value = "#onlySignIp")
    public int createDataSource(String onlySignIp,@Param("dbName")String dbName);

Switch data source

At first I thought that this would allow you to create a database directly in the system. The underlying dynamic-datasource will generate a responsibility chain when initially loading. There are three nodes, namely DsHeaderProcessor, DsSessionProcessor, and DsSpelExpressionProcessor, respectively, corresponding to #header, #session and spel expressions. The source code is as follows:

    @Bean
    @ConditionalOnMissingBean
    public DsProcessor dsProcessor(BeanFactory beanFactory) {
        DsHeaderProcessor headerProcessor = new DsHeaderProcessor();
        DsSessionProcessor sessionProcessor = new DsSessionProcessor();
        DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
        (new BeanFactoryResolver(beanFactory));
        (sessionProcessor);
        (spelExpressionProcessor);
        return headerProcessor;
    }

Here, according to the underlying code, there should be no problem. It seems that the chain of responsibility that is customized with it is not good. Here, I rewrite this chain of responsibility myself (that is, copy the source code myself and inject it into the spring container), and then rewrite it.DsSpelExpressionProcessor,passspelExpression to select the data source.

public class DsSpelExpressionProcessor extends DsProcessor {

    /**
      * Parameter discoverer
      */
    private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
    /**
      * Express syntax parser
      */
    private static final ExpressionParser PARSER = new SpelExpressionParser();
    /**
      * Template for parsing context
      * If the default setting is not set, the way to get the value from the parameter #param1
      * Set the value method after the specified template ParserContext.TEMPLATE_EXPRESSION: #{#param1}
      * issues: /baomidou/dynamic-datasource-spring-boot-starter/issues/199
      */
    private ParserContext parserContext = new ParserContext() {

        @Override
        public boolean isTemplate() {
            return false;
        }

        @Override
        public String getExpressionPrefix() {
            return null;
        }

        @Override
        public String getExpressionSuffix() {
            return null;
        }
    };
    private BeanResolver beanResolver;

    @Override
    public boolean matches(String key) {
        return true;
    }

    @Override
    public String doDetermineDatasource(MethodInvocation invocation, String key) {
        Object[] arguments = ();
        StandardEvaluationContext context = new StandardEvaluationContext(arguments);
        //The first parameter is used by default        String replace = ("#", "");
        (replace,arguments[0]);
        final Object value = (key, parserContext).getValue(context);
        return value == null ? null : ();
    }


    public void setParserContext(ParserContext parserContext) {
         = parserContext;
    }

    public void setBeanResolver(BeanResolver beanResolver) {
         = beanResolver;
    }
}

This allows dynamic switching of data sources to be achieved with @DS annotation.

Follow-up questions

When it is necessary to switch the data source, pass the corresponding data source key information as the first parameter of the Mapper

For example:

    /**
      * Call different data connections to generate a new database
      * @param onlySignIp
      * @param dbName
      * @return
      */
    @DS(value = "#onlySignIp")
    public int createDataSource(String onlySignIp,@Param("dbName")String dbName);

When switching data sources, the **@DS** annotation must be added, and the key of the corresponding data source must be passed in as the first parameter.

summary

Through the analysis of dynamic-datasource-spring-boot-starter, we simply implement the operation of customizing the creation of data sources and switching the data sources

This is the article about SpringBoot using dynamic-datasource-spring-boot-starter to solve multi-data source problems. For more related SpringBoot multi-data source content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!