栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

mybatis-plus 多数据源

mybatis-plus 多数据源

关键词

mybatis-plus 、 druid  、跨不同数据源、同一个连接跨库查询

项目场景描述

1.项目数据库db_data_link和dolphinscheduler数据库db_ds使用同一个mysql实例,分不同的库,为了降低复杂度,给db_data_link的用户赋予了db_ds数据库的只读权限,可以跨库查询

2.项目中还会用到其他的数据库,如hive的meta数据库,也想使用mybatis的快捷查询功能

3.项目中主库只有一个,涉及到事务,其他的都不需要

多种方式调研
方案核心思路描述总结
方案1baomidou官方提供的dynamic-datasource-spring-boot-starter ,功能强大,可以满足各类场景需求,官方帮助文档1.核心原理是做数据源动态切换,mybatis-plus的配置只有一个,在执行时根据注解@ds 来实现切换

缺点:

1.在使用的时候仍然需要在具体的mapper或者service加上注解来区分数据源

2.有遇到过多数据源事务提交不满足预期的问题

方案2配置多数据源、多sqlSessionFactory、多事务多数据源完全隔离,使用各自的sqlSessionFactory

缺点:

1.多事务时必须要指定事务,但是也可只配置一个事务

2.配置多个数据源时会跟很多的AutoConfiguration冲突:DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class

3.mybatis-plus默认配置不生效了,有点不能接受

方案3方案2的升级版本

将方案2的缺点想办法跳过

1.很多数据源相关的AutoConfiguration都是数据源相关的,只有一个数据源的时候才会生效,多数据源时只让默认数据源注入spring的bean容器

2.非主数据源在配置sqlSessionFactory时创建,不走spring容器

3.非主数据源不配置事务,这样事务只有一个,使用时就不需要手动指定事务了

优点:

不改变已有的任何使用姿势,很丝滑!

1.数据源配置和mybatis-plus都走spring的默认配置

2.事务使用也不用改 

跨库查询

1.mybatis-plus 支持默认全局参数替换,sql中的库名可以设置成动态参数

variables: dsDb:dolphinscheduler200 # 配置ds的数据库名称

2.domain类表名称无法动态解析,需要使用mybatis-plus的sqlInject插件

@TableName("${dsDb}.t_ds_task_definition_log")

@Bean
public MybatisPlusInterceptor tableNameInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
    dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
        return TableNameUtils.evaluateTableName(tableName);
    });
    interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
    // 3.4.3.2 作废该方式
    // dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
    return interceptor;
}

public class TableNameUtils {

    @Value("${mybatis-plus.configuration.variables:}")
    private Properties variables;

    public static TableNameUtils getInstance() {
        return ApplicationContextHolder.getInstance(TableNameUtils.class);
    }

    public static String evaluateTableName(String tableName1) {
        String parse = new GenericTokenParser("${", "}", id -> {
            Object o = TableNameUtils.getInstance().variables.get(id);
            return o.toString();
        }).parse(tableName1);
        return parse;
    }
}

核心配置流程,简单到不敢相信!
@Configuration
@MapperScan(basePackages = "com.redstarclouds.datalink.common.hive.meta.mapper", sqlSessionFactoryRef = "hivemetaSqlSessionFactory")
public class HivemetaDataSourceContext {

    @Bean(name = "hivemetaSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        HiveConfig hiveConfig = ApplicationContextHolder.getInstance(HiveConfig.class);
        HikariDataSource ds = new HikariDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUsername(hiveConfig.hivemetadataUser);
        ds.setPassword(hiveConfig.hivemetadataPassWord);
        ds.setJdbcUrl(hiveConfig.hivemetadataJdbcUrl);

        MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(ds);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/hive/*.xml"));
        return sessionFactoryBean.getObject();
    }

}

注意:
1.扫描包是需要需要指定sqlSessionFactoryRef = "hivemetaSqlSessionFactory"
2.xml文件路径需要和默认的确认开,统一个路径好像只能被一个SqlSessionFactory加载,不是很确定,但是这么做就对了
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/674177.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号