1. Introduction: Necessity and application scenarios of multi-data sources
In modern software development, as business complexity increases and data volumes expand rapidly, an application may need to access multiple databases simultaneously to meet different data processing needs.
For example, an e-commerce system may require a database to process transaction data and another to analyze user behavior. This is the necessity of multi-data source configuration.
Why do you need multiple data sources?
- Business logic separation: Different databases can carry different business modules. For example, order processing and user analysis can be carried out in different databases separately, making the business clearer and improving the maintainability of the system.
- Performance optimization: By distributing requests to a special database, a single database can be avoided from becoming a performance bottleneck due to excessive requests, thereby improving the performance of the entire application.
- Data security and isolation: Sensitive data can be stored separately in a more secure database, while ordinary data can be processed in a conventional security-level database, thereby improving data security.
- Technology diversity: Different database technologies (such as relational and non-relational databases) have their specific advantages, and multi-data source configuration allows leveraging the advantages of various database technologies in a single project.
Application scenarios
- Big data analysis and real-time business system parallel: In many enterprise-level applications, real-time business databases and big data analysis databases are usually needed to manage separately to avoid complex data analysis operations affecting the performance of core business systems.
- Microservice architecture: In a microservice architecture, individual microservices may require independent database instances to maintain the autonomy and decoupling of services.
- Legacy system integration: During the integration of new and old systems, it may be necessary to access the database of new and old systems at the same time to ensure the integrity and consistency of data.
- Cross-regional data processing: Globalized businesses may require the deployment of databases in different regions to reduce data access latency and comply with geographic data regulations.
Through these scenarios, we can see that the configuration of multi-data sources is not only a technical requirement, but also part of business development and data management strategies.
2. Data source configuration in Spring Boot
Spring Boot greatly simplifies database connections and operations of Java applications. It supports quick up and running with automatic configuration, but requires some additional configuration when dealing with multiple data sources.
Here are detailed instructions on how to configure a single default data source in Spring Boot and how to scale to multiple data sources.
2.1 Introduction to the default data source configuration
In Spring Boot, configuring a default data source is very simple. You just need toor
Add relevant database connection configuration to the file. Spring Boot uses these properties to automatically configure data sources and JPA or JDBC templates.
Example -Configuration:
=jdbc:mysql://localhost:3306/mydatabase =myuser =mypass -class-name=
These configurations tell Spring Boot how to connect to the database and which JDBC driver to use. Spring Boot supports most mainstream databases and automatically configures connection pools (default isHikariCP
)。
2.2 How to configure multiple data sources in Spring Boot
Configuring multiple data sources requires more manual settings. You need to define the configuration for each data source and make sure Spring Boot can correctly distinguish and manage them. Here are the steps to configure multiple data sources:
Step 1: Define the data source configuration
First, you need to define a different prefix for each data source in the configuration file. For example:
#Main Data Source=jdbc:mysql://localhost:3306/primary_db =root =123456 -class-name= # Auxiliary data source=jdbc:mysql://localhost:3306/secondary_db =root =123456 -class-name=
Step 2: Create a data source configuration class
You need to create configuration classes to load and distinguish these data sources. Each data source should have its own configuration class and @Bean definition.
@Configuration public class DataSourceConfig { @Bean(name = "primaryDataSource") @Primary @ConfigurationProperties(prefix = "") public DataSource primaryDataSource() { return ().build(); } @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "") public DataSource secondaryDataSource() { return ().build(); } }
In this configuration,@Primary
The annotation marks the primary data source, which means that if multiple data sources are available, Spring Boot will default to use the@Primary
data source.
Step 3: Configure JdbcTemplate or EntityManager
For each data source, you may need to configure oneJdbcTemplate
orEntityManager
Easy to operate the database.
@Bean public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); }
Through the above steps, you can configure and use multiple data sources in your Spring Boot application. This configuration method can not only meet complex business needs, but also help you better manage and maintain different data environments.
3. Integrate MyBatis with Multiple Data Sources
MyBatis is a popular persistence layer framework that supports customized SQL, stored procedures, and advanced mapping. Integrating MyBatis for multi-data source management in Spring Boot applications requires some specific configuration to ensure that each data source is correctly bound to the corresponding SQL map and transaction manager.
Configuring MyBatis to use multiple data sources
To configure MyBatis to use multiple data sources, you need to define theSqlSessionFactory
andTransactionManager
. This ensures that MyBatis can provide independent session and transaction control for each database connection.
- Define the data source: Define multiple data sources as mentioned earlier.
-
Create SqlSessionFactory: Create one for each data source
SqlSessionFactory
, which is the core component of MyBatis, used to manage all SQL operations of MyBatis. - Configuring TransactionManager: Configure a transaction manager for each data source to ensure the correct management of transactions.
@Configuration public class MyBatisConfig { @Bean @Primary public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); (dataSource); return (); } @Bean public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); (dataSource); return (); } @Bean @Primary public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
Data source specification of the Mapper interface
Defining differentSqlSessionFactory
After that, you need to specify which data source should be used for each Mapper interface or XML mapping file. This is usually achieved by using specific annotations on the Mapper interface or by configuration.
-
use
@MapperScan
Annotation Specify the data source: Can be used in the configuration class@MapperScan
Annotation specifies different packagesSqlSessionFactory
。
@Configuration @MapperScan(basePackages = "", sqlSessionFactoryRef = "primarySqlSessionFactory") public class PrimaryDataSourceConfig { // Primary data source configuration } @Configuration @MapperScan(basePackages = "", sqlSessionFactoryRef = "secondarySqlSessionFactory") public class SecondaryDataSourceConfig { // Secondary data source configuration }
In this way, you can ensure that the Mapper interface for each data source will only be associated with the specifiedSqlSessionFactory
interaction, thereby realizing data source isolation. Such configuration makes managing multiple data sources more flexible and efficient in large projects.
4. Dynamic routing of data sources
In a multi-data source environment, dynamic data source routing becomes a powerful strategy that allows applications to select different databases based on specific logic or conditions at runtime. This is especially useful for applications that require dynamic switching of data sources based on user requests, transaction characteristics, or other business logic.
4.1 What is data source routing?
Data source routing is a mechanism that dynamically determines which data source to go to based on certain rules. For example, in a multi-tenant system, each tenant may have its own database, and the system needs to dynamically switch to the corresponding database based on the current user's tenant information.
4.2 Implementing a simple dynamic data source routing
In order to implement dynamic data source routing, we usually need to create a dynamic data source router, which inherits fromAbstractRoutingDataSource
, and rewritedetermineCurrentLookupKey()
Method to decide which data source key to use.
Here is a simple implementation example:
1. Define dynamic data source classes
import ; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // DynamicDataSourceContextHolder is used to hold the data source identifier used by the current thread return (); } }
2. Configure dynamic data sources
In Spring configuration file, you need to configureDynamicDataSource
As the data source and specify the actual data source map.
@Configuration public class DataSourceConfig { @Bean public DataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // Set the default data source (primaryDataSource()); // Configure multiple data sources Map<Object, Object> dataSourceMap = new HashMap<>(); ("primary", primaryDataSource()); ("secondary", secondaryDataSource()); (dataSourceMap); return dynamicDataSource; } @Bean public DataSource primaryDataSource() { return new HikariDataSource(); // Configure the main data source } @Bean public DataSource secondaryDataSource() { return new HikariDataSource(); // Configure secondary data sources } }
3. Use@Transactional
Specify the data source
In the service or data access layer, you can specify@Transactional
Annotatedvalue
Properties to select a specific data source.
@Service public class UserService { @Transactional(value = "primaryTransactionManager") public void addUser(User user) { // Add user using the primary data source } @Transactional(value = "secondaryTransactionManager") public User findUser(String username) { // Find users using secondary data sources } }
Such a setting allows applications to flexibly select appropriate data sources according to business needs at runtime, thereby achieving more complex data operation strategies and higher data operation flexibility.
5. Transaction management configuration
Transaction management becomes particularly important when dealing with multiple data sources, as improper transaction processing can lead to data inconsistency and other serious problems. In Spring Boot applications, correctly configuring and managing transactions under multiple data sources is the key to ensuring data integrity and consistency.
How to manage transactions under multiple data sources
Local Affairs:
- Local Affairsis the simplest transaction type, it only involves a single data source.
- In Spring Boot, you can configure a transaction manager for each data source.
- Then, you can use it in the service layer
@Transactional
Annotation to specify which transaction manager to use.
Example configuration transaction manager:
@Bean public DataSourceTransactionManager transactionManager1(DataSource dataSource1) { return new DataSourceTransactionManager(dataSource1); } @Bean public DataSourceTransactionManager transactionManager2(DataSource dataSource2) { return new DataSourceTransactionManager(dataSource2); }
Use the specified transaction manager:
@Transactional(transactionManager = "transactionManager1") public void someDataServiceMethod() { // Business logic}
Global transactions:
- Global transactions(also known as distributed transactions) involve multiple data sources or services.
- In Spring Boot, you can use JTA (Java Transaction API) to configure a global transaction manager such as Atomikos or Bitronix.
Configure the global transaction manager (using Atomikos as an example):
@Bean(initMethod = "init", destroyMethod = "close") public UserTransactionManager atomikosTransactionManager() throws Throwable { UserTransactionManager userTransactionManager = new UserTransactionManager(); (false); return userTransactionManager; } @Bean public JtaTransactionManager transactionManager(UserTransactionManager userTransactionManager) { JtaTransactionManager transactionManager = new JtaTransactionManager(); (userTransactionManager); (userTransactionManager); return transactionManager; }
Use the global transaction manager at the service layer:
@Transactional public void someDataServiceMethod() { // Business logic involves multiple data sources}
Configure global and local transactions
When configuring transaction management, you need to decide whether each business scenario is suitable for local transactions or global transactions. Local transactions are simple and have good performance, suitable for single data source operations. Global transactions are suitable for operations that require multiple databases or services, but may result in higher performance overhead.
Make sure to clearly distinguish different transaction managers when configuring and using transactions, especially when using@Transactional
Specify the correct manager when annotating to avoid data problems caused by transaction management chaos.
6. Practical example: Complete multi-data source configuration example
In this section, we will show you how to configure and use multiple data sources in a Spring Boot application with a practical example. This example will include configuration files, data source configuration, MyBatis integration, and dynamic data source implementations.
Example Overview
Suppose we have an application that needs to access two databases at the same time: one is the main database (for daily business operations), and the other is the audit database (for recording audit logs). We will use MySQL as the database.
Step 1: Add dependencies
First, inAdd necessary dependencies to:
<dependencies> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> </dependencies>
Step 2: Configure the data source
existConfigure two data sources:
spring: datasource: primary: jdbc-url: jdbc:mysql://localhost:3306/business_db username: user1 password: pass1 driver-class-name: audit: jdbc-url: jdbc:mysql://localhost:3306/audit_db username: user2 password: pass2 driver-class-name:
Step 3: Configure the data source Bean and MyBatis
Configure two data sources and correspondingSqlSessionFactory
:
@Configuration public class DataSourceConfig { @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "") public DataSource primaryDataSource() { return ().build(); } @Bean(name = "auditDataSource") @ConfigurationProperties(prefix = "") public DataSource auditDataSource() { return ().build(); } @Bean(name = "primarySqlSessionFactory") public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); (dataSource); return (); } @Bean(name = "auditSqlSessionFactory") public SqlSessionFactory auditSqlSessionFactory(@Qualifier("auditDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); (dataSource); return (); } }
Step 4: Dynamic Data Source Routing
Implementing a simple dynamic data source routing can be extendedAbstractRoutingDataSource
:
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return (); } }
HereDataSourceContext
It is a tool class that manages data source keys (such as thread-local variables) that determines which data source the current thread should use.
Step 5: Configure and use
Finally, you need to switch the data source as needed in the business logic. This is usually done by using annotations on the service layer method or by calling it directlyDataSourceContext
To set up the data source.
This example provides a basic framework for multi-data source configuration, you can adjust and extend it according to actual needs, such as adding transaction manager configuration, optimizing connection pool settings, etc.
7. Simplify multi-data source management-dynamic
dynamic-datasource-spring-boot-starter
is a data source management framework for Spring Boot applications. It is not only a simple component, but a complete solution designed to simplify the configuration and management of multiple data sources. This framework provides the ability to switch data sources dynamically at runtime, which is very useful for applications that need to connect to multiple databases, especially in scenarios where read and write separation or connection to different types of databases are required.
Functions and features
dynamic-datasource-spring-boot-starter
The main functions and features include:
- Simplify multi-data source configuration: Make configuration simple and intuitive by declaring multiple data sources in the configuration file of your Spring Boot application.
-
Dynamic data source switching: Provides method or class-based annotations (e.g.
@DS
), allowing developers to easily specify which data source should be used for specific operations. - Flexible data source routing: Supports dynamic selection of data sources based on business logic, such as switching data sources based on user request parameters or other logic.
- Supports master-slave replication: Very suitable for database read and write separation, improving database operation efficiency and performance.
- Integration with the Spring ecosystem: Good integration with other Spring components such as Spring Boot and Spring Data JPA, making it seamlessly work with existing Spring applications.
Application scenarios
- Read and write separation: In applications that need to deal with a large number of read operations and relatively few write operations, read operations can be pointed to the slave database and write operations can be pointed to the master database.
- Performance and usability: By distributing requests to multiple data sources, the response time and overall performance of the application can be improved.
-
Data isolation: In a multi-tenant system, each tenant may need a separate database. use
dynamic-datasource-spring-boot-starter
Each tenant's data source can be easily managed.
Anyway,dynamic-datasource-spring-boot-starter
It is a powerful multi-data source management framework that is ideal for complex applications that require high flexibility and powerful data source management capabilities. It greatly improves development efficiency and application performance by simplifying configuration and increasing the ability to switch data sources at runtime.
Introduce dependencies
First, make sure that your Spring Boot project has been addeddynamic-datasource-spring-boot-starter
dependency. If you haven't added it yet, you canAdd the following dependencies:
<dependency> <groupId></groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>Version</version> </dependency>
Version selection based on the dependent version of the actual project
Configure multiple data sources
existor
Configure multiple data sources in the file. For example, use the YAML format to configure it as follows:
spring: datasource: dynamic: primary: master # Set the main data source datasource: master: url: jdbc:mysql://localhost:3306/master_db username: root password: password driver-class-name: slave: url: jdbc:mysql://localhost:3306/slave_db username: root password: password driver-class-name:
Use @DS annotation
@DS
is an annotation for multiple data sources separation, providing the ability to use multiple data sources simultaneously in the same application. This annotation belongs todynamic-datasource-spring-boot-starter
Library for dynamically managing multiple data sources in Spring Boot applications. Here is how to use it@DS
Some basic information and examples of annotations.
Use in method
import ; @Service public class SomeService { @DS("master") public void writeToMaster() { // The operation here will use the master data source in the configuration } @DS("slave") public void readFromSlave() { // The operation here will use the slave data source in the configuration } }
Use on the class
If all methods in a class should use the same data source, you can@DS
Annotations are placed at the class level:
import ; @DS("slave") @Service public class ReadOnlyService { // All methods will use slave data source public void queryData() { // ... } }
Things to note
- Ensure the keys of the data source (e.g.
master
andslave
) matches the name you defined in the configuration file. - use
@DS
When annotating, the dynamic data source will switch to the specified data source before the method is called, and switch back to the original data source after the method is executed. - Consider transaction management policies, especially when using multiple data sources, multiple transaction managers may need to be configured.
In this way,@DS
Annotations provide a very flexible and powerful mechanism for handling multiple data sources, making it simple and direct to selecting different data sources according to business needs in the same application.
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.