在许多企业级应用中,可能需要访问多个数据库。MyBatis 可以通过配置多个数据源和动态切换数据源来支持多数据库操作。下面介绍如何在 MyBatis 中配置和使用多个数据源。
1. 多数据源的基本配置
1.1 配置多个数据源
要支持多个数据源,首先需要在 Spring 或 Spring Boot 中配置不同的数据源。假设我们要连接两个数据库 db1
和 db2
,可以通过以下步骤进行配置。
Spring Boot 示例:
-
application.yml
配置文件:
spring:datasource:db1:url: jdbc:mysql://localhost:3306/db1username: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverdb2:url: jdbc:mysql://localhost:3306/db2username: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driver
-
定义数据源配置类:
@Configuration
public class DataSourceConfig {
@Primary@Bean(name = "db1DataSource")@ConfigurationProperties(prefix = "spring.datasource.db1")public DataSource db1DataSource() {return DataSourceBuilder.create().build();}
@Bean(name = "db2DataSource")@ConfigurationProperties(prefix = "spring.datasource.db2")public DataSource db2DataSource() {return DataSourceBuilder.create().build();}
}
-
定义 SqlSessionFactory 和 SqlSessionTemplate:
@Configuration
@MapperScan(basePackages = "com.example.mapper.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate")
public class Db1MyBatisConfig {
@Bean(name = "db1SqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);return sessionFactory.getObject();}
@Bean(name = "db1SqlSessionTemplate")public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}
}
@Configuration
@MapperScan(basePackages = "com.example.mapper.db2", sqlSessionTemplateRef = "db2SqlSessionTemplate")
public class Db2MyBatisConfig {
@Bean(name = "db2SqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);return sessionFactory.getObject();}
@Bean(name = "db2SqlSessionTemplate")public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}
}
1.2 使用不同数据源的 Mapper
通过以上配置,不同包下的 Mapper 将使用不同的数据源。假设 UserMapper
使用 db1
,OrderMapper
使用 db2
。
@Mapper
public interface UserMapper {// 使用 db1 数据源User findUserById(Integer id);
}
@Mapper
public interface OrderMapper {// 使用 db2 数据源Order findOrderById(Integer id);
}
2. 动态切换数据源
有时我们需要在运行时动态地切换数据源,比如在同一个 Service 中操作不同的数据源。可以通过 Spring 的 AbstractRoutingDataSource
实现动态切换。
2.1 定义动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSourceKey) {contextHolder.set(dataSourceKey);}
public static String getDataSource() {return contextHolder.get();}
public static void clearDataSource() {contextHolder.remove();}
@Overrideprotected Object determineCurrentLookupKey() {return getDataSource();}
}
2.2 配置数据源和 SqlSessionFactory
@Configuration
public class DynamicDataSourceConfig {
@Bean@Primarypublic DataSource dataSource(@Qualifier("db1DataSource") DataSource db1DataSource,@Qualifier("db2DataSource") DataSource db2DataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("db1", db1DataSource);targetDataSources.put("db2", db2DataSource);
DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setTargetDataSources(targetDataSources);dynamicDataSource.setDefaultTargetDataSource(db1DataSource);return dynamicDataSource;}
@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource);return sessionFactoryBean.getObject();}
@Beanpublic SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}
}
2.3 在 Service 中动态切换数据源
@Service
public class UserService {
@Autowiredprivate UserMapper userMapper;
@Autowiredprivate OrderMapper orderMapper;
public User getUserFromDb1(Integer id) {DynamicDataSource.setDataSource("db1");try {return userMapper.findUserById(id);} finally {DynamicDataSource.clearDataSource();}}
public Order getOrderFromDb2(Integer id) {DynamicDataSource.setDataSource("db2");try {return orderMapper.findOrderById(id);} finally {DynamicDataSource.clearDataSource();}}
}
3. 总结
MyBatis 支持通过配置多个数据源和动态切换数据源来实现多数据库操作:
-
多数据源静态配置:通过在 Spring 配置中定义多个
DataSource
、SqlSessionFactory
和SqlSessionTemplate
来实现静态多数据源支持。不同包下的 Mapper 自动使用指定的数据源。 -
动态数据源切换:通过实现
AbstractRoutingDataSource
动态数据源切换机制,能够在运行时动态地选择不同的数据源,这对于需要在同一事务中切换不同数据库操作的场景特别有用。
通过这些方法,MyBatis 可以灵活地支持多数据库操作,以满足复杂的业务需求。