大家好,我是锋哥。今天分享关于【MyBatis如何实现动态数据源切换?】面试题。希望对大家有帮助;
MyBatis如何实现动态数据源切换?
超硬核AI学习资料,现在永久免费了!
在MyBatis中实现动态数据源切换,通常需要依赖Spring的动态数据源管理机制,结合一些自定义的切换策略。以下是实现动态数据源切换的基本步骤:
1. 配置数据源
首先,在配置文件中配置多个数据源。例如,配置两个数据源:masterDataSource
和 slaveDataSource
。
<bean id="masterDataSource" class="org.apache.commons.dbcp2.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/master_db"/><property name="username" value="root"/><property name="password" value="root"/>
</bean><bean id="slaveDataSource" class="org.apache.commons.dbcp2.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/slave_db"/><property name="username" value="root"/><property name="password" value="root"/>
</bean>
2. 定义动态数据源
创建一个自定义的数据源类,它能够切换不同的数据源。AbstractRoutingDataSource
是Spring提供的一个抽象类,适用于实现动态数据源。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {// 返回当前的数据源标识(如:master 或 slave)return DataSourceContextHolder.getDataSourceType();}
}
3. 数据源上下文管理
为了管理当前使用的数据源,可以创建一个 DataSourceContextHolder
类,用来存储和获取当前线程的数据源标识。
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();}
}
4. 配置动态数据源
在Spring配置中使用 DynamicDataSource
替代传统的单一数据源。
<bean id="dataSource" class="com.example.DynamicDataSource"><property name="defaultTargetDataSource" ref="masterDataSource"/><property name="targetDataSources"><map><entry key="master" value-ref="masterDataSource"/><entry key="slave" value-ref="slaveDataSource"/></map></property>
</bean>
5. AOP实现数据源切换
使用Spring AOP(面向切面编程)来切换数据源。可以通过注解或者在方法执行前动态修改当前线程的 DataSource
。
例如,创建一个注解 @DataSource
来标记需要切换数据源的方法:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {String value() default "master"; // 默认使用master数据源
}
然后,创建一个切面(Aspect),根据注解切换数据源:
@Aspect
@Component
public class DataSourceAspect {@Before("@annotation(dataSource)")public void changeDataSource(DataSource dataSource) {// 切换数据源DataSourceContextHolder.setDataSourceType(dataSource.value());}@After("@annotation(dataSource)")public void restoreDataSource(DataSource dataSource) {// 切换回默认数据源DataSourceContextHolder.clearDataSourceType();}
}
6. 在服务层使用注解切换数据源
在需要切换数据源的方法上使用 @DataSource
注解:
@Service
public class UserService {@DataSource("master") // 使用master数据源public void addUser(User user) {// 执行数据库操作}@DataSource("slave") // 使用slave数据源public List<User> getUsers() {// 执行数据库查询return userRepository.findAll();}
}
7. 使用完毕后清理数据源
在每次请求结束后,确保清理 ThreadLocal
中存储的数据源标识,避免线程池复用时出现错误。
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();}
}
总结:
- 数据源管理:使用
DynamicDataSource
来管理多个数据源。 - 数据源切换:通过
DataSourceContextHolder
类和Spring AOP机制,在方法执行时切换数据源。 - 使用场景:动态切换数据源通常用于读写分离,或者多数据库操作的场景。
这样,你就可以在 MyBatis 中根据需要动态地切换数据源了。