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多数据源连接和切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Spring Bean生命周期之BeanDefinition的合并过程详解
这篇文章主要为大家详细介绍了Spring Bean生命周期之BeanDefinition的合并过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助2022-03-03
Java中四种访问控制权限解析(private、default、protected、public)
java当中有4种访问修饰限定符privat、default(默认访问权限),protected以及public,本文就详细的介绍一下这四种方法的具体使用,感兴趣的可以了解一下2023-05-05
5分钟搭建SpringCloud Eureka服务注册中心的实现
这篇文章主要介绍了5分钟搭建SpringCloud Eureka服务注册中心的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2021-03-03
SpringBoot2.x过后static下的静态资源无法访问的问题
这篇文章主要介绍了SpringBoot2.x过后static下的静态资源无法访问的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-01-01


最新评论