SpringBoot中实现多数据源连接和切换的方案
引言
在Spring Boot中,通过AbstractRoutingDataSource实现多数据源连接是一种常见的做法。这种技术允许你在运行时动态地切换数据源,从而支持对多个数据库的操作。Spring Boot中配置和使用AbstractRoutingDataSource来实现多数据源连接。
1. 添加依赖
pom.xml文件的依赖,比如Spring Data JPA和数据库驱动:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 其他依赖 --> </dependencies>
2. 配置数据源属性
在application.yml
或application.properties
中配置多个数据源的信息。例如:
spring: datasource: primary: url: jdbc:mysql://localhost:3306/primary_db username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver secondary: url: jdbc:mysql://localhost:3306/secondary_db username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver
3. 创建数据源配置类
创建两个数据源配置类,分别用于配置主数据源和次数据源。
@Configuration public class DataSourceConfig { @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } }
4. 创建自定义数据源路由类
扩展AbstractRoutingDataSource
类,并根据上下文信息动态返回数据源。
public class DynamicRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }
5. 创建数据源上下文持有者
用于在运行时设置和获取当前的数据源类型。
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } }
6. 配置多数据源
将数据源配置到Spring上下文中,并指定默认的数据源。
@Configuration @EnableTransactionManagement @EnableJpaRepositories( basePackages = "com.example.repository", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager" ) public class DataSourceRoutingConfig { @Autowired @Qualifier("primaryDataSource") private DataSource primaryDataSource; @Autowired @Qualifier("secondaryDataSource") private DataSource secondaryDataSource; @Bean public DataSource dataSource() { DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource(); Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("primary", primaryDataSource); targetDataSources.put("secondary", secondaryDataSource); routingDataSource.setTargetDataSources(targetDataSources); routingDataSource.setDefaultTargetDataSource(primaryDataSource); return routingDataSource; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(dataSource()) .packages("com.example.entity") .persistenceUnit("multiple-pu") .build(); } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } }
7. 使用AOP切换数据源
通过AOP在方法执行前设置数据源类型,并在方法执行后清除。
@Aspect @Component public class DataSourceAspect { @Before("@annotation(targetDataSource)") public void changeDataSource(JoinPoint point, TargetDataSource targetDataSource) throws Throwable { DataSourceContextHolder.setDataSourceType(targetDataSource.value()); } @After("@annotation(targetDataSource)") public void clearDataSource(JoinPoint point, TargetDataSource targetDataSource) { DataSourceContextHolder.clearDataSourceType(); } }
自定义注解TargetDataSource
:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface TargetDataSource { String value(); }
8. 使用自定义注解切换数据源
在需要使用特定数据源的方法或类上使用@TargetDataSource
注解。
@Service public class UserService { @Autowired private UserRepository userRepository; @TargetDataSource("primary") public User findUserById(Long id) { return userRepository.findById(id).orElse(null); } @TargetDataSource("secondary") public User findUserBySecondaryId(Long id) { // 假设secondary数据库有一个类似的表结构 return userRepository.findById(id).orElse(null); } }
到此这篇关于SpringBoot中实现多数据源连接和切换的方案的文章就介绍到这了,更多相关SpringBoot多数据源连接和切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Springboot整合nacos报错无法连接nacos的解决
这篇文章主要介绍了Springboot整合nacos报错无法连接nacos的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-06-06SpringBoot配置Spring Security的实现示例
本文主要介绍了SpringBoot配置Spring Security的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2024-10-10mapstruct的用法之qualifiedByName示例详解
qualifiedByName的意思就是使用这个Mapper接口中的指定的默认方法去处理这个属性的转换,而不是简单的get set,今天通过本文给大家介绍下mapstruct的用法之qualifiedByName示例详解,感兴趣的朋友一起看看吧2022-04-04
最新评论