Java高频面试题:MyBatis如何实现动态数据源切换?

张开发
2026/5/19 13:13:51 15 分钟阅读
Java高频面试题:MyBatis如何实现动态数据源切换?
大家好我是锋哥。今天分享关于【Java高频面试题MyBatis如何实现动态数据源切换】面试题 。希望对大家有帮助Java高频面试题MyBatis如何实现动态数据源切换1️⃣ 基本思路在 MyBatis或 Spring MyBatis中动态切换数据源的核心思想是定义多个数据源DataSource。使用一个动态数据源路由器DynamicDataSource在运行时根据上下文决定使用哪个数据源。在方法或线程执行前设置当前线程使用的数据源标识通常用ThreadLocal保存。MyBatis 的SqlSession或 SpringJdbcTemplate会通过动态数据源路由器获取当前的数据源。关键点线程安全。每个线程单独维护自己的数据源标识防止并发下数据源错乱。2️⃣ 核心实现步骤2.1 定义数据源通常在application.yml或application.properties中配置多个数据源例如spring: datasource: master: url: jdbc:mysql://localhost:3306/master username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver slave: url: jdbc:mysql://localhost:3306/slave username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver在 Spring 中配置对应的DataSourceBeanBean Primary ConfigurationProperties(prefix spring.datasource.master) public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } Bean ConfigurationProperties(prefix spring.datasource.slave) public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); }2.2 创建动态数据源public class DynamicDataSource extends AbstractRoutingDataSource { // 核心方法根据当前线程的数据源标识返回对应 DataSource Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }DataSourceContextHolder用于管理线程数据源public class DataSourceContextHolder { private static final ThreadLocalString CONTEXT new ThreadLocal(); public static void setDataSource(String dataSource) { CONTEXT.set(dataSource); } public static String getDataSource() { return CONTEXT.get(); } public static void clear() { CONTEXT.remove(); } }然后在配置类里Bean public DataSource dynamicDataSource(DataSource masterDataSource, DataSource slaveDataSource) { MapObject, Object targetDataSources new HashMap(); targetDataSources.put(master, masterDataSource); targetDataSources.put(slave, slaveDataSource); DynamicDataSource dynamicDataSource new DynamicDataSource(); dynamicDataSource.setDefaultTargetDataSource(masterDataSource); // 默认数据源 dynamicDataSource.setTargetDataSources(targetDataSources); return dynamicDataSource; }2.3 MyBatis 配置动态数据源在 Spring Boot 中通常直接配置 MyBatis 使用动态数据源Bean public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource) throws Exception { SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean(); sessionFactory.setDataSource(dynamicDataSource); return sessionFactory.getObject(); }2.4 在代码中切换数据源可以在服务方法上通过AOP 或注解来切换数据源例如Target({ ElementType.METHOD, ElementType.TYPE }) Retention(RetentionPolicy.RUNTIME) public interface DataSource { String value() default master; }AOP 切面实现Aspect Component public class DataSourceAspect { Before(annotation(dataSource)) public void switchDataSource(DataSource dataSource) { DataSourceContextHolder.setDataSource(dataSource.value()); } After(annotation(dataSource)) public void clearDataSource(DataSource dataSource) { DataSourceContextHolder.clear(); } }然后在 Service 方法上标注Service public class UserService { DataSource(slave) public ListUser getUsersFromSlave() { return userMapper.selectAll(); } DataSource(master) public void insertUser(User user) { userMapper.insert(user); } }✅ 这样就实现了按方法动态切换数据源。3️⃣ 注意事项事务管理动态数据源切换必须配合 Spring 的事务管理否则可能出现事务跨数据源异常。通常使用Transactional注解配合AbstractRoutingDataSource即可。线程安全必须使用ThreadLocal来保证每个线程独立使用数据源标识否则并发请求可能混乱。性能考虑切换数据源比单一数据源略有开销尤其是在高并发下需要注意连接池的配置。 总结MyBatis 的动态数据源切换本质是AbstractRoutingDataSource ThreadLocal的组合通过 AOP 或手动设置当前线程的数据源来实现方法级的数据源切换。

更多文章