MyBatis-Plus多数据源支持,40. MyBatis-Plus如何处理多数据源配置?如何实现动态切换数据源?

通过研究MyBatis-Plus官网

多数据源支持

多数据源支持 | MyBatis-Plus

dynamic-datasource 是一个开源的 Spring Boot 多数据源启动器,提供了丰富的功能,包括数据源分组、敏感信息加密、独立初始化表结构等。

使用方法:

  1. 引入依赖

 
  1. <!--多个数据源-->
  2. <dependency>
  3. <groupId>com.baomidou</groupId>
  4. <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  5. <version>3.2.0</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.baomidou</groupId>
  9. <artifactId>mybatis-plus-boot-starter</artifactId>
  10. <version>3.2.0</version>
  11. </dependency>
 

 

注意:项目中已经存在的mybatis的依赖需要注释,防止下面的共同存在的mybatis-spring产生冲突

  1. 配置数据源:如

 
  1. spring.datasource.dynamic.primary=db1
  2. spring.datasource.dynamic.strict=false
  3. spring.datasource.dynamic.datasource.db1.url=jdbc:mysql://localhost:3306/ican?characterEncoding=utf-8&useUnicode=true&serverTimezone=UTC&allowMultiQueries=true
  4. spring.datasource.dynamic.datasource.db1.username=root
  5. spring.datasource.dynamic.datasource.db1.password=123456
  6. spring.datasource.dynamic.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
  7.  
  8. spring.datasource.dynamic.datasource.db2.url=jdbc:mysql://192.168.21.37:3306/210_bm_inventory?useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
  9. spring.datasource.dynamic.datasource.db2.username=root
  10. spring.datasource.dynamic.datasource.db2.password=root123
  11. spring.datasource.dynamic.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
 

 

一共配置了两个数据源 db1和db2 其中spring.datasource.dynamic.primary=db1配置主数据源为db1(没有注解时默认为主数据源)

spring.datasource.dynamic.strict=false 这个设置的是严格模式,true为开启,false为关闭。

开启@DS(db3) db3并不存在会直接报错,不开启则会采用主数据源进行二次尝试

  1. 使用 @DS 切换数据源:

 
  1. @Mapper
  2.  
  3. public interface InventoryDao {
  4. @PageX
  5. @DS("db2")
  6. List<Inventory> select(InventoryQuery query);
  7. Integer insert(Inventory inventory);
  8. Integer insertBatch(List<Inventory> inventorys);
  9. Integer update(Integer id, int optionQty, int version,String lastUpdateBy);
  10. Integer delete(Integer id);
  11. }
 

 

类或者方法上都能加注释,注释括号里可以为组名(也就是2里面配置的db1,db2)也可以为具体某个库的名称。

目前主要用于wms仓储系统直接操作北猫商城里的inventory表。

如果引入不了依赖选择删除maven库中的具体文件夹或者依赖冲突可以选择直接删除总的maven库,或者解决冲突:进入pom

红线的就是有冲突的包

可以根据手动删除依赖、在Plugins下载Maven Helper插件进行解决、或者配置冲突子类不启动

在使用MyBatis-Plus的Spring Boot项目中,处理多数据源和动态切换数据源的需求常见于企业级应用中。下面详细介绍如何配置多数据源以及如何实现动态切换数据源。

 

1. 配置多数据源

 

1.1 在application.yml中配置多个数据源

首先,在Spring Boot的application.yml中配置多个数据源。

 
  1. spring:
  2. datasource:
  3.   db1:
  4.     url: jdbc:mysql://localhost:3306/db1
  5.     username: root
  6.     password: password
  7.     driver-class-name: com.mysql.cj.jdbc.Driver
  8.   db2:
  9.     url: jdbc:mysql://localhost:3306/db2
  10.     username: root
  11.     password: password
  12.     driver-class-name: com.mysql.cj.jdbc.Driver
 
 

1.2 定义数据源配置类

定义数据源配置类,配置不同的数据源和MyBatis的SqlSessionFactory。

 

 
  1. @Configuration
  2. public class DataSourceConfig {
  3. ​
  4.   @Primary
  5.   @Bean(name = "db1DataSource")
  6.   @ConfigurationProperties(prefix = "spring.datasource.db1")
  7.   public DataSource db1DataSource() {
  8.       return DataSourceBuilder.create().build();
  9.   }
  10. ​
  11.   @Bean(name = "db2DataSource")
  12.   @ConfigurationProperties(prefix = "spring.datasource.db2")
  13.   public DataSource db2DataSource() {
  14.       return DataSourceBuilder.create().build();
  15.   }
  16. ​
  17.   @Primary
  18.   @Bean(name = "db1SqlSessionFactory")
  19.   public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
  20.       SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  21.       sessionFactory.setDataSource(dataSource);
  22.       return sessionFactory.getObject();
  23.   }
  24. ​
  25.   @Bean(name = "db2SqlSessionFactory")
  26.   public SqlSessionFactory db2SqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
  27.       SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  28.       sessionFactory.setDataSource(dataSource);
  29.       return sessionFactory.getObject();
  30.   }
  31. ​
  32.   @Primary
  33.   @Bean(name = "db1SqlSessionTemplate")
  34.   public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
  35.       return new SqlSessionTemplate(sqlSessionFactory);
  36.   }
  37. ​
  38.   @Bean(name = "db2SqlSessionTemplate")
  39.   public SqlSessionTemplate db2SqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
  40.       return new SqlSessionTemplate(sqlSessionFactory);
  41.   }
  42. }
 
 

1.3 配置Mapper扫描路径

使用@MapperScan注解指定不同数据源的Mapper接口所在的包路径。

 
  1. @Configuration
  2. @MapperScan(basePackages = "com.example.mapper.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate")
  3. public class Db1MyBatisConfig {
  4. }
  5. ​
  6. @Configuration
  7. @MapperScan(basePackages = "com.example.mapper.db2", sqlSessionTemplateRef = "db2SqlSessionTemplate")
  8. public class Db2MyBatisConfig {
  9. }
 
 

2. 实现动态切换数据源

 

2.1 定义动态数据源类

通过继承AbstractRoutingDataSource实现动态数据源的切换。

 
  1. public class DynamicDataSource extends AbstractRoutingDataSource {
  2. ​
  3.   private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
  4. ​
  5.   public static void setDataSource(String dataSourceKey) {
  6.       contextHolder.set(dataSourceKey);
  7.   }
  8. ​
  9.   public static String getDataSource() {
  10.       return contextHolder.get();
  11.   }
  12. ​
  13.   public static void clearDataSource() {
  14.       contextHolder.remove();
  15.   }
  16. ​
  17.   @Override
  18.   protected Object determineCurrentLookupKey() {
  19.       return getDataSource();
  20.   }
  21. }
 
 

2.2 配置动态数据源

在配置类中将多个数据源注册到DynamicDataSource,并设置默认数据源。

 

 
  1. @Configuration
  2. public class DynamicDataSourceConfig {
  3. ​
  4.   @Bean
  5.   public DataSource dynamicDataSource(@Qualifier("db1DataSource") DataSource db1DataSource,
  6.                                       @Qualifier("db2DataSource") DataSource db2DataSource) {
  7.       Map<Object, Object> targetDataSources = new HashMap<>();
  8.       targetDataSources.put("db1", db1DataSource);
  9.       targetDataSources.put("db2", db2DataSource);
  10. ​
  11.       DynamicDataSource dynamicDataSource = new DynamicDataSource();
  12.       dynamicDataSource.setTargetDataSources(targetDataSources);
  13.       dynamicDataSource.setDefaultTargetDataSource(db1DataSource);
  14.       return dynamicDataSource;
  15.   }
  16. ​
  17.   @Bean
  18.   public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
  19.       SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
  20.       sessionFactoryBean.setDataSource(dynamicDataSource);
  21.       return sessionFactoryBean.getObject();
  22.   }
  23. ​
  24.   @Bean
  25.   public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
  26.       return new SqlSessionTemplate(sqlSessionFactory);
  27.   }
  28. }
 
 

2.3 动态切换数据源

在需要切换数据源的Service方法中,使用DynamicDataSource.setDataSource()来指定当前线程的数据源。

 

 
  1. @Service
  2. public class UserService {
  3. ​
  4.   @Autowired
  5.   private UserMapper userMapper;
  6. ​
  7.   @Autowired
  8.   private OrderMapper orderMapper;
  9. ​
  10.   public User getUserFromDb1(Integer id) {
  11.       DynamicDataSource.setDataSource("db1");
  12.       try {
  13.           return userMapper.findUserById(id);
  14.       } finally {
  15.           DynamicDataSource.clearDataSource();
  16.       }
  17.   }
  18. ​
  19.   public Order getOrderFromDb2(Integer id) {
  20.       DynamicDataSource.setDataSource("db2");
  21.       try {
  22.           return orderMapper.findOrderById(id);
  23.       } finally {
  24.           DynamicDataSource.clearDataSource();
  25.       }
  26.   }
  27. }
 
 

3. 使用注解实现数据源切换

为了简化数据源切换的操作,可以使用自定义注解来切换数据源。

 

3.1 创建自定义注解

 

 
  1. @Target({ElementType.METHOD, ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface DataSource {
  5.   String value() default "db1";
  6. }
 
 

3.2 实现AOP切面

使用AOP切面拦截带有@DataSource注解的方法,动态切换数据源。

 

 
  1. @Aspect
  2. @Component
  3. public class DynamicDataSourceAspect {
  4. ​
  5.   @Before("@annotation(dataSource)")
  6.   public void changeDataSource(JoinPoint point, DataSource dataSource) {
  7.       DynamicDataSource.setDataSource(dataSource.value());
  8.   }
  9. ​
  10.   @After("@annotation(dataSource)")
  11.   public void clearDataSource(JoinPoint point, DataSource dataSource) {
  12.       DynamicDataSource.clearDataSource();
  13.   }
  14. }
 
 

3.3 使用自定义注解

现在可以在Service层方法上使用@DataSource注解来动态切换数据源。

 

@Service
public class UserService {
​
    @Autowired
    private UserMapper userMapper;
​
    @Autowired
    private OrderMapper orderMapper;
​
    @DataSource("db1")
    public User getUserFromDb1(Integer id) {
        return userMapper.findUserById(id);
    }
​
    @DataSource("db2")
    public Order getOrderFromDb2(Integer id) {
        return orderMapper.findOrderById(id);
    }
}

4. 总结

MyBatis-Plus在Spring Boot项目中支持多数据源操作,并通过配置多个数据源和动态数据源实现动态切换数据源:

  1. 多数据源配置:通过配置多个DataSource、SqlSessionFactory、SqlSessionTemplate来支持多数据源操作,不同包下的Mapper接口使用不同的数据源。

  2. 动态切换数据源:通过实现AbstractRoutingDataSource和AOP切面,可以在运行时动态切换数据源,适用于复杂业务场景。

  3. 注解实现数据源切换:通过自定义注解和AOP结合,简化了数据源的动态切换操作,使代码更加简洁和易于维护。

通过这些配置,MyBatis-Plus可以轻松地支持多数据库的操作,并在需要时动态地切换数据源。

36. MyBatis如何支持多数据库操作?如何配置不同的数据源?

在许多企业级应用中,可能需要访问多个数据库。MyBatis 可以通过配置多个数据源和动态切换数据源来支持多数据库操作。下面介绍如何在 MyBatis 中配置和使用多个数据源。

 

1. 多数据源的基本配置

 

1.1 配置多个数据源

要支持多个数据源,首先需要在 Spring 或 Spring Boot 中配置不同的数据源。假设我们要连接两个数据库 db1 和 db2,可以通过以下步骤进行配置。

Spring Boot 示例:

  • application.yml 配置文件:

 
  1. spring:
  2. datasource:
  3.   db1:
  4.     url: jdbc:mysql://localhost:3306/db1
  5.     username: root
  6.     password: password
  7.     driver-class-name: com.mysql.cj.jdbc.Driver
  8.   db2:
  9.     url: jdbc:mysql://localhost:3306/db2
  10.     username: root
  11.     password: password
  12.     driver-class-name: com.mysql.cj.jdbc.Driver
 
  • 定义数据源配置类:

 
  1. @Configuration
  2. public class DataSourceConfig {
  3. ​
  4.   @Primary
  5.   @Bean(name = "db1DataSource")
  6.   @ConfigurationProperties(prefix = "spring.datasource.db1")
  7.   public DataSource db1DataSource() {
  8.       return DataSourceBuilder.create().build();
  9.   }
  10. ​
  11.   @Bean(name = "db2DataSource")
  12.   @ConfigurationProperties(prefix = "spring.datasource.db2")
  13.   public DataSource db2DataSource() {
  14.       return DataSourceBuilder.create().build();
  15.   }
  16. }
 
  • 定义 SqlSessionFactory 和 SqlSessionTemplate:

 
  1. @Configuration
  2. @MapperScan(basePackages = "com.example.mapper.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate")
  3. public class Db1MyBatisConfig {
  4. ​
  5.   @Bean(name = "db1SqlSessionFactory")
  6.   public SqlSessionFactory sqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
  7.       SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  8.       sessionFactory.setDataSource(dataSource);
  9.       return sessionFactory.getObject();
  10.   }
  11. ​
  12.   @Bean(name = "db1SqlSessionTemplate")
  13.   public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
  14.       return new SqlSessionTemplate(sqlSessionFactory);
  15.   }
  16. }
  17. ​
  18. @Configuration
  19. @MapperScan(basePackages = "com.example.mapper.db2", sqlSessionTemplateRef = "db2SqlSessionTemplate")
  20. public class Db2MyBatisConfig {
  21. ​
  22.   @Bean(name = "db2SqlSessionFactory")
  23.   public SqlSessionFactory sqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
  24.       SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  25.       sessionFactory.setDataSource(dataSource);
  26.       return sessionFactory.getObject();
  27.   }
  28. ​
  29.   @Bean(name = "db2SqlSessionTemplate")
  30.   public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
  31.       return new SqlSessionTemplate(sqlSessionFactory);
  32.   }
  33. }
 
 

1.2 使用不同数据源的 Mapper

通过以上配置,不同包下的 Mapper 将使用不同的数据源。假设 UserMapper 使用 db1,OrderMapper 使用 db2。

 
  1. @Mapper
  2. public interface UserMapper {
  3.   // 使用 db1 数据源
  4.   User findUserById(Integer id);
  5. }
  6. ​
  7. @Mapper
  8. public interface OrderMapper {
  9.   // 使用 db2 数据源
  10.   Order findOrderById(Integer id);
  11. }
 
 

2. 动态切换数据源

有时我们需要在运行时动态地切换数据源,比如在同一个 Service 中操作不同的数据源。可以通过 Spring 的 AbstractRoutingDataSource 实现动态切换。

 

2.1 定义动态数据源

 
  1. public class DynamicDataSource extends AbstractRoutingDataSource {
  2. ​
  3.   private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
  4. ​
  5.   public static void setDataSource(String dataSourceKey) {
  6.       contextHolder.set(dataSourceKey);
  7.   }
  8. ​
  9.   public static String getDataSource() {
  10.       return contextHolder.get();
  11.   }
  12. ​
  13.   public static void clearDataSource() {
  14.       contextHolder.remove();
  15.   }
  16. ​
  17.   @Override
  18.   protected Object determineCurrentLookupKey() {
  19.       return getDataSource();
  20.   }
  21. }
 
 

2.2 配置数据源和 SqlSessionFactory

 
  1. @Configuration
  2. public class DynamicDataSourceConfig {
  3. ​
  4.   @Bean
  5.   @Primary
  6.   public DataSource dataSource(@Qualifier("db1DataSource") DataSource db1DataSource,
  7.                                 @Qualifier("db2DataSource") DataSource db2DataSource) {
  8.       Map<Object, Object> targetDataSources = new HashMap<>();
  9.       targetDataSources.put("db1", db1DataSource);
  10.       targetDataSources.put("db2", db2DataSource);
  11. ​
  12.       DynamicDataSource dynamicDataSource = new DynamicDataSource();
  13.       dynamicDataSource.setTargetDataSources(targetDataSources);
  14.       dynamicDataSource.setDefaultTargetDataSource(db1DataSource);
  15.       return dynamicDataSource;
  16.   }
  17. ​
  18.   @Bean
  19.   public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
  20.       SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
  21.       sessionFactoryBean.setDataSource(dataSource);
  22.       return sessionFactoryBean.getObject();
  23.   }
  24. ​
  25.   @Bean
  26.   public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  27.       return new SqlSessionTemplate(sqlSessionFactory);
  28.   }
  29. }
 
 

2.3 在 Service 中动态切换数据源

 
  1. @Service
  2. public class UserService {
  3. ​
  4.   @Autowired
  5.   private UserMapper userMapper;
  6. ​
  7.   @Autowired
  8.   private OrderMapper orderMapper;
  9. ​
  10.   public User getUserFromDb1(Integer id) {
  11.       DynamicDataSource.setDataSource("db1");
  12.       try {
  13.           return userMapper.findUserById(id);
  14.       } finally {
  15.           DynamicDataSource.clearDataSource();
  16.       }
  17.   }
  18. ​
  19.   public Order getOrderFromDb2(Integer id) {
  20.       DynamicDataSource.setDataSource("db2");
  21.       try {
  22.           return orderMapper.findOrderById(id);
  23.       } finally {
  24.           DynamicDataSource.clearDataSource();
  25.       }
  26.   }
  27. }
 
 

3. 总结

MyBatis 支持通过配置多个数据源和动态切换数据源来实现多数据库操作:

  1. 多数据源静态配置:通过在 Spring 配置中定义多个 DataSource、SqlSessionFactory 和 SqlSessionTemplate 来实现静态多数据源支持。不同包下的 Mapper 自动使用指定的数据源。

  2. 动态数据源切换:通过实现 AbstractRoutingDataSource 动态数据源切换机制,能够在运行时动态地选择不同的数据源,这对于需要在同一事务中切换不同数据库操作的场景特别有用。

通过这些方法,MyBatis 可以灵活地支持多数据库操作,以满足复杂的业务需求。

posted @ 2025-01-03 09:21  charyGao  阅读(1273)  评论(0)    收藏  举报