掌握 Spring Boot + MyBatis-Plus 动态数据源切换,只要5分钟!

数据量猛增,通过动态数据源切换,我们不仅能提高查询效率,还能保证系统的高可用性。

通过将操作集中在主库操作分散到多个从库,可以有效减轻数据库的压力。

pom.xml中添加以下依赖:

 

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

application.yml中的数据源配置

 

yaml

spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
replica:
url: jdbc:mysql://localhost:3306/replica_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

在这里,我们配置了两个数据源,

一个主库primary

一个从库replica

这样我们就可以在业务中区分读写操作了。

枚举类型与数据源上下文

为了实现动态数据源切换,我们需要定义数据源的类型,并通过上下文管理当前数据源。

DatabaseType枚举的设计
 

java

public enum DatabaseType {
PRIMARY, // 主库
REPLICA // 从库
}

DataSourceContextHolder的实现与作用
 

java

public class DataSourceContextHolder {

// 使用ThreadLocal存储当前线程的数据源类型
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();

// 设置数据源类型
public static void setDatabaseType(DatabaseType type) {
contextHolder.set(type);
}

// 获取数据源类型
public static DatabaseType getDatabaseType() {
return contextHolder.get();
}

// 清除数据源类型
public static void clearDatabaseType() {
contextHolder.remove();
}
}

通过上述代码,我们可以在不同的线程中安全地设置和获取当前数据源的类型。

动态数据源的实现机制

动态数据源的核心是继承并重写AbstractRoutingDataSource类。

DynamicDataSource类的继承与重写
 

java

public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 从上下文中获取当前数据源的类型
return DataSourceContextHolder.getDatabaseType();
}
}

通过继承AbstractRoutingDataSource,我们可以在运行时根据上下文动态切换数据源

为了方便使用,我们可以设计一个自定义注解@DataSource来标识需要切换数据源的方法或类。

@DataSource注解的定义
 

java

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
DatabaseType value() default DatabaseType.PRIMARY; // 默认使用主库
}

注解在类和方法上的使用示例

图片

使用自定义注解,我们可以方便地在方法上切换数据源。

数据源切换的AOP实现

通过AOP,我们可以在方法执行前后切换数据源。

DataSourceAspect切面类的编写
 

java

@Aspect
@Component
public class DataSourceAspect {

@Around("@annotation(dataSource)")
public Object switchDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
try {
// 在方法执行前设置数据源
DataSourceContextHolder.setDatabaseType(dataSource.value());
return point.proceed(); // 执行目标方法
} finally {
// 在方法执行后清除数据源
DataSourceContextHolder.clearDatabaseType();
}
}
}

通过环绕通知,我们可以在方法执行前后设置和清除数据源,确保数据源切换的正确性。

配置类负责创建和管理多个数据源,并将它们注册到Spring容器中。

DataSourceConfig的职责与实现
 

java

@Configuration
public class DataSourceConfig {

@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build(); // 创建主数据源
}

@Bean
@ConfigurationProperties(prefix = "spring.datasource.replica")
public DataSource replicaDataSource() {
return DataSourceBuilder.create().build(); // 创建从数据源
}

@Bean
public DataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseType.PRIMARY, primaryDataSource());
targetDataSources.put(DatabaseType.REPLICA, replicaDataSource());

DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setDefaultTargetDataSource(primaryDataSource()); // 设置默认数据源
dataSource.setTargetDataSources(targetDataSources); // 设置目标数据源
return dataSource;
}
}

通过这个配置类,我们可以将多个数据源注册到Spring容器中,并设置默认数据源和目标数据源。

为了在MyBatis-Plus中使用动态数据源,我们需要配置SqlSessionFactory和SqlSessionTemplate。

DynamicDataSourceConfig的配置
 

java

@Configuration
@MapperScan("com.example.mapper")
public class DynamicDataSourceConfig {

@Autowired
private DataSource dataSource;

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}

@Bean
public SqlSessionTemplate sqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}

通过配置SqlSessionFactorySqlSessionTemplate,我们可以确保MyBatis-Plus能够使用动态数据源。

主从数据库同步策略

实时同步方案的推荐

图片

图片

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值