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
-
Naming Specifications:
- Use clear naming for each data source (such as customerDS, orderDS)
- Package structure is separated by data source (/.secondary)
Connection pool configuration:
-pool-size=10 -pool-size=5
-
Monitoring indicators:
- Configure independent monitoring for each data source
- Expose data source health metrics using Spring Actuator
-
Performance considerations:
- High-frequency accessed data sources use larger connection pools
- Read and write separation scenarios consider master-slave data sources
-
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!