Springboot 整合MybatisPlus 多数据源

源码下载

目前暂时使用的实现方式

基于 AbstractRoutingDataSource扩展,加AOP动态切换数据源
分包实现

环境搭建

数据库脚本准备

demo 测试使用 两个 库 db0 db1

create database db0;
create database db1;
use db0;
drop table if exists t_user;
CREATE TABLE `t_user` (
  `id` int(11) PRIMARY key auto_increment COMMENT '用户编号',
  `user_name` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号',
  UNIQUE KEY `idx_user_name` (`user_name`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

insert into t_user(user_name) values('阿离');
insert into t_user(user_name) values('奏');
insert into t_user(user_name) values('阿花 ');


use db1;
drop table if exists t_order;
CREATE TABLE `t_order` (
  `id` int(11) PRIMARY key auto_increment COMMENT '订单编号',
  `user_id` int(16) DEFAULT NULL COMMENT '用户编号'

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='订单表';

insert into t_order(user_id) values(123);
insert into t_order(user_id) values(45);
insert into t_order(user_id) values(789);


项目大致结构

在这里插入图片描述

依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--AOP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!-- 实现对数据库连接池的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <!--MyBatis 及 插件依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.13</version>
        </dependency>

    </dependencies>

配置文件

# db0

spring.datasource.druid.db0.url=jdbc:mysql://127.0.0.1:3306/db0?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.druid.db0.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.db0.username=root
spring.datasource.druid.db0.password=123456
# db1
spring.datasource.druid.db1.url=jdbc:mysql://127.0.0.1:3306/db1?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.druid.db1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.db1.username=root
spring.datasource.druid.db1.password=123456

配置类

MybatisPlusConfig

@EnableTransactionManagement
@Configuration
@MapperScan(basePackages ={"com.zou.dao.db0.mapper","com.zou.dao.db1.mapper"})
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }

    @Bean(name = Constant.DB0)
    @ConfigurationProperties(prefix = "spring.datasource.druid.db0")
    public DataSource db0() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = Constant.DB1)
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.druid.db1")
    public DataSource db1() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 动态数据源配置
     * @param db0
     * @param db1
     * @return javax.sql.DataSource
     * @author wh
     * @date 2020/7/21
     */
    @Bean
    public DataSource multipleDataSource(@Qualifier(Constant.DB0) DataSource db0,
                                         @Qualifier(Constant.DB1) DataSource db1) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(Constant.DB0, db0);
        targetDataSources.put(Constant.DB1, db1);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        // 设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(db0);
        return dynamicDataSource;
    }

    /**
     *  事务管理器
     * @param
     * @return DataSourceTransactionManager
     * @author wh
     * @date 2020/7/27
     */
    @Bean
    public DataSourceTransactionManager transactionManager () {
        return new DataSourceTransactionManager( multipleDataSource(db0(), db1()) );
    }

    @Bean
    @Primary
    public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean () throws Exception{
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
        // 实体类别名
        bean.setTypeAliasesPackage("com.zou.model");
        MybatisConfiguration configuration = new MybatisConfiguration();
        //开启下划线转驼峰
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        bean.setDataSource(multipleDataSource(db0(), db1()));
        return bean;
    }

}

DynamicDataSource

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        final String lookupKey = DbContextHolder.getDbType();
        DbContextHolder.clearDbType();
        return  lookupKey;
    }
}

DbContextHolder

public class DbContextHolder {

    private static final ThreadLocal<String> contextHolder = ThreadLocal.withInitial(String::new);

    /**
     * 设置数据源
     * @param dbType
     * @return void
     * @author wh
     * @date 2020/7/21
     */
    public static void setDbType(String dbType) {
        contextHolder.set(dbType);
    }

    /**
     * 取得当前数据源
     * @param
     * @return java.lang.String
     * @author wh
     * @date 2020/7/21
     */
    public static String getDbType() {
        System.out.println("获取数据源为:" + contextHolder.get());
        return contextHolder.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

DataSourceSwitchAspect

@Component
@Order(value = -100)
@Aspect
@Slf4j
public class DataSourceSwitchAspect {

    private static final String DB0= "execution(* com.zou.dao.db0..*.*(..))";

    private static final String DB1 = "execution(* com.zou.dao.db1..*.*(..))";

    @Pointcut(DB0)
    private void db0Aspect() {
    }

    @Pointcut(DB1)
    private void db1Aspect() {
    }


    @Before("db0Aspect()")
    public void dsc() {
        DbContextHolder.setDbType(Constant.DB0);
    }

    @Before("db1Aspect()")
    public void admin() {
        DbContextHolder.setDbType(Constant.DB1);
    }


}

目前动态切换数据源已经配置成功了,我们仅需要在db0,db1开发自己业务即可动态切换,由于篇幅这里不给出其他类,感兴趣可以自己下载源码

测试

运行测试类 TestService 中的 getOrderAndUser 方法即可
在这里插入图片描述

这里可以看到是查询了我们配置的两个库

后续将介绍配置多个 SqlSessionTemplate 来实现多数据源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值