Spring Boot应用中实现多数据源配置与切换的最佳实践

软件测试视界 2019-04-24 ⋅ 60 阅读

在开发Web应用过程中,我们经常需要与不同的数据库交互,有时候甚至需要同时访问多个数据源。Spring Boot提供了强大的支持来简化多数据源的配置和管理,本文将介绍在Spring Boot应用中实现多数据源配置与切换的最佳实践。

添加依赖

首先,在pom.xml文件中添加Spring Boot对于多数据源的支持依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
</dependencies>

配置数据源

application.properties文件中配置多个数据源的相关信息:

# 数据源1
spring.datasource.url=jdbc:mysql://localhost:3306/database1
spring.datasource.username=your-username
spring.datasource.password=your-password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 数据源2
datasource2.url=jdbc:mysql://localhost:3306/database2
datasource2.username=your-username
datasource2.password=your-password
datasource2.driver-class-name=com.mysql.cj.jdbc.Driver

配置数据源的配置类

创建一个DataSourceConfig类,用于配置数据源:

@Configuration
public class DataSourceConfig {
    
    @Primary
    @Bean(name = "dataSource1")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSource2")
    @ConfigurationProperties(prefix = "datasource2")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }
}

创建数据源的JdbcTemplate

在每个数据源上创建一个对应的JdbcTemplate,用于执行SQL语句:

@Configuration
public class JdbcTemplateConfig {
    
    @Bean(name = "jdbcTemplate1")
    public JdbcTemplate jdbcTemplate1(@Qualifier("dataSource1") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean(name = "jdbcTemplate2")
    public JdbcTemplate jdbcTemplate2(@Qualifier("dataSource2") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

创建数据源的事务管理器

为每个数据源创建对应的事务管理器,实现事务的管理:

@Configuration
public class TransactionManagerConfig {
    
    @Bean(name = "transactionManager1")
    public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "transactionManager2")
    public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

创建数据源的Repository

在每个数据源上创建对应的Repository接口,用于对数据库进行操作:

@Repository
public interface UserRepository1 extends JpaRepository<User, Long> {
    // ...
}

@Repository
public interface UserRepository2 extends JpaRepository<User, Long> {
    // ...
}

动态切换数据源

为了实现动态切换数据源,可以通过自定义注解和AOP的方式来实现。首先,创建一个自定义注解@DataSource,用于标识具体的方法使用哪个数据源:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value() default "dataSource1";
}

然后,创建一个AOP切面类DataSourceAspect,在该切面类中根据@DataSource注解的值来切换数据源:

@Aspect
@Configuration
public class DataSourceAspect {

    @Before("@annotation(dataSource)")
    public void switchDataSource(JoinPoint point, DataSource dataSource) {
        String dataSourceName = dataSource.value();
        if (StringUtils.isNotBlank(dataSourceName)) {
            DynamicDataSourceContextHolder.setDataSourceType(dataSourceName);
        }
    }

    @After("@annotation(dataSource)")
    public void restoreDataSource(JoinPoint point, DataSource dataSource) {
        DynamicDataSourceContextHolder.clearDataSourceType();
    }
}

配置AOP切面

最后,将DataSourceAspect配置成一个AOP切面,实现数据源的动态切换:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

    @Autowired
    private DataSource dataSource1;

    @Autowired
    private DataSource dataSource2;

    @Bean
    public DataSourceAspect dataSourceAspect() {
        return new DataSourceAspect();
    }

    @Bean
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSource1);
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("dataSource1", dataSource1);
        targetDataSources.put("dataSource2", dataSource2);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

测试数据源切换

最后,我们可以在业务代码中使用@DataSource注解来指定具体的数据源:

@Service
public class UserService {

    @Autowired
    private UserRepository1 userRepository1;

    @Autowired
    private UserRepository2 userRepository2;

    @DataSource("dataSource1")
    public List<User> getAllUsersFromDataSource1() {
        return userRepository1.findAll();
    }

    @DataSource("dataSource2")
    public List<User> getAllUsersFromDataSource2() {
        return userRepository2.findAll();
    }
}

以上就是在Spring Boot应用中实现多数据源配置与切换的最佳实践。通过使用Spring Boot的相关组件,我们可以轻松地实现多个数据源的配置和切换,提高应用的灵活性和可扩展性。


全部评论: 0

    我有话说: