当前位置:   article > 正文

Mybatis-Plus 之【数据源配置(含多数据源配置)】_mybatisplus多数据源

mybatisplus多数据源

MybatisPlus【数据源配置(单、多数据源)】


前言

MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。


一、单数据源配置

使用方法

坐标依赖:

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.5.1</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.28</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

application.yml配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通用配置

配置类

@Configuration
@MapperScan(basePackages = {"com.xx.**.mapper"})
public class MybatisPlusConfig {
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
    	//新的分页插件配置方法(Mybatis Plus 3.4.0版本及其之后的版本)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

二、多数据源配置

坐标依赖【新增】:

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
	<version>3.1.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

application.yml配置

spring:
  datasource:
    db1:
      url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    db2:
      url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

1.单配置类

使用方法【配合注解@DS(“db1”)】

@DS(“db1”)是一个MyBatis的注解,用于动态数据源切换。在MyBatis中,我们可以通过在mapper.xml文件或者Java接口上使用@DS注解来指定数据源。

实体类

@Data
@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField("name")
    private String name;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Service

@Service
@DS("db1")
public class UserServiceImpl implements UserService {
 
  @Autowired
  private JdbcTemplate jdbcTemplate;
 
  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
 
  @Override
  @DS("db1_1")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解。

2.多配置类

使用方法【根据不同Mapper路径配置不同数据源】

多配置类【根据自己需要使用的插件进行配置、不需要的可以删除】

@Configuration
@MapperScan(basePackages = "com.xx.xx.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class db1DataSourceConfig {
    // 将这个对象放入Spring容器中
    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource getDateSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "db1SqlSessionFactory")
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource datasource)
            throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        //configuration配置bean
        //MybatisConfiguration configuration = new MybatisConfiguration();
        //configuration.setMapUnderscoreToCamelCase(true);
        //configuration.setCacheEnabled(false);
        // 配置打印sql语句s
        //configuration.setLogImpl(StdOutImpl.class);
        // 添加自定义SQL注入
        //bean.setConfiguration(configuration);

        //插件对象
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //动态表名
        //DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
		//可以传多个表名参数,指定哪些表使用MonthTableNameHandler处理表名称
        //dynamicTableNameInnerInterceptor.setTableNameHandler(new MonthTableNameHandler("t_table_name"));
		//以拦截器的方式处理表名称
		//可以传递多个拦截器,即:可以传递多个表名处理器TableNameHandler
        //mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);


        //分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        bean.setDataSource(datasource);
        // 设置mybatis的xml所在位置
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db1/*.xml"));
        bean.setPlugins(mybatisPlusInterceptor);
        return bean.getObject();
    }

    @Bean("db1SqlSessionTemplate")
    public SqlSessionTemplate db1SqlSessionTemplate(
            @Qualifier("db1SqlSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }

    @Bean("db1TransactionManager")
    public PlatformTransactionManager db1TransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
@Configuration
@MapperScan(basePackages = "com.xx.xx.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class db2DataSourceConfig {
    // 将这个对象放入Spring容器中
    @Bean(name = "db2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource getDateSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "db2SqlSessionFactory")
    public SqlSessionFactory db2SqlSessionFactory(@Qualifier("db2DataSource") DataSource datasource)
            throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        // 设置mybatis的xml所在位置
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db2/*.xml"));
        bean.setPlugins(mybatisPlusInterceptor);
        return bean.getObject();
    }

    @Bean("db2SqlSessionTemplate")
    public SqlSessionTemplate db2SqlSessionTemplate(
            @Qualifier("db2SqlSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }

    @Bean("db2TransactionManager")
    public PlatformTransactionManager db2TransactionManager(@Qualifier("db2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

数据源为db1

package com.xx.xx.mapper.db1;
/**
 Mapper 接口
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

启动类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DynamicApplication{
    public static void main(String[] args) {
        SpringApplication.run(DynamicApplication.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.AOP动态切换数据源

使用方法【自定义注解方式】

动态数据源切换类

@NoArgsConstructor
public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<String> DB_CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 取得当前使用的数据源
     * @return 当前使用的数据源
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    /**
     * 设置数据源
     * @param dataSource 数据源
     */
    public static void setDataSource(String dataSource) {
        DB_CONTEXT_HOLDER.set(dataSource);
    }

    /**
     * 获取当前数据源
     * @return 数据源
     */
    public static String getDataSource() {
        return DB_CONTEXT_HOLDER.get();
    }

    /**
     * 清除上下文
     */
    public static void clearDataSource() {
        DB_CONTEXT_HOLDER.remove();
    }

    /**
     * 设置默认数据源,和可切换的数据源Map
     * @param defaultTargetDataSource 默认数据源
     * @param targetDataSources 可切换的数据源Map
     */
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

多数据源配置类

@Component
@Configuration
public class DataSourceConfig {

    /**
     * 创建数据源db1
     * @return 数据源db1
     */
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.db1")
    public DataSource db1DataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 创建数据源db2
     * @return 数据源db2
     */
    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.db2")
    public DataSource db2DataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 数据源配置
     * @param db1数据源db1
     * @param db2数据源db2
     * @return 动态数据源切换对象。
     * @Description @Primary赋予该类型bean更高的优先级,使至少有一个bean有资格作为autowire的候选者。
     */
    @Bean
    @Primary
    public DataSource dataSource(@Qualifier("db1") DataSource db1,
                                 @Qualifier("db2") DataSource db2) {
        Map<Object, Object> dsMap = new HashMap<>(2);
        dsMap.put("db1", db1);
        dsMap.put("db2", db2);
        return new DynamicDataSource(db1, dsMap);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

启动类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@Import({DataSourceConfig.class})
public class DynamicApplication{
    public static void main(String[] args) {
        SpringApplication.run(DynamicApplication.class, args);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

创建自定义注解【用来指定使用哪个数据源】

/**
 * @Description 在方法上使用,用于指定使用哪个数据源
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String name() default "";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

创建AOP【根据注解的参数切换数据源】

/**
 * @Description 多数据源切换AOP,@Order(-100)是为了保证AOP在事务注解之前生效,Order的值越小,优先级越高
 */
@Aspect
@Component
@Order(-100)
@Slf4j
public class DataSourceAspect {

    @Pointcut("execution(* com.xx.xx.service..*.*(..))")
    private void dsPointCut() {
    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前指定的数据源
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        DataSource dataSource = method.getAnnotation(DataSource.class);

        if (Objects.isNull(dataSource)) {
            // 使用默认数据源
            DynamicDataSource.setDataSource("db1");
            log.info("默认数据源启动");
        } else {
            // 匹配到的话,设置到动态数据源上下文中
            DynamicDataSource.setDataSource(dataSource.name());
            log.info("匹配到数据源:{}", dataSource.name());
        }

        try {
            // 执行目标方法,返回值即为当前方法的返回值
            return joinPoint.proceed();
        } finally {
            // 方法执行完毕之后,销毁当前数据源信息,进行垃圾回收
            DynamicDataSource.clearDataSource();
            log.info("清空数据源");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

Service

@Service
public class UserServiceImpl implements UserService {
 
  @Autowired
  private JdbcTemplate jdbcTemplate;
 
  @DataSource(name = "db1")
  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
 
  @Override
  @DataSource(name = "db2")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

总结

1、三种数据源配置的方法可根据实际需要选择
2、使用 @DS 注解切换数据源时,使用springboot数据源的自动配置,需要将DataSourceConfig配置注释掉
3、使用 @DataSource 自定义注解时,排除springboot数据源的自动配置,引入DataSourceConfig配置

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/525287
推荐阅读
相关标签
  

闽ICP备14008679号