mybatis-plus动态表名实现

mybatis-plus动态表名实现

1.使用场景

一个mybatis entity 对应多张表(表明不同的表–> 多张表结构一致只有表名称不同),在使用时,可以动态映射表名称。
比如:按照时间分表,某些业务冷热数据分离后数据存在不同的表中等

2.一定要时常注意工具的更新,不吃亏

因为工作需要,最近需要实现一个类似如下业务等功能交互:
mybatis-plus动态表名实现_第1张图片
简单的描述就是:有一部分的表数据,采用了外部同步的模式,同步到了doris中,在业务中采用双数据源的方式,数据写在mysql,读走doris (此处不考虑数据同步的延迟问题 ,这是个大问题,但我们这篇文章先不考虑这个问题)。
要实现上面的方案,需要解决以下几个问题:

  1. 双数据源的问题
  2. doris/mysql中库和表的名称不一致(例如:上图绿色打底的表,在mysql和doris中表的结构一致,但在mysql中库.表名为 : databaseA.tableA ,在doris中则为 databaseB.ods_tableB_s)

在之前项目研究中,因为有自己去自定义dao层mapper的方法,mybatis表中的方法对应的sql在项目启动时就已经生成好了对应的sql模板,在程序运行中,只是用参数代替即可。
mybatis-plus动态表名实现_第2张图片
例如上图,因为我之前用的mybatis-plus 的版本比较低,在生成模板时实际上就已经确定了表的名称。这就导致了无法在使用的时候重新替换。为了实现这个功能,自己实现的时候也是一直往我如何在生成模板语句的时候就直接把我想要的表名替换替换进去。 在实现的差不多的时候,同事来了一句,mybatis-plus不是支持的吗? hhhh,所以说,还是要去关注一下你在项目中所用到的jar包的迭代更新哦,会发现很多,然后开始偷懒。
mybatis-plus动态表名实现_第3张图片

3.对mybatis-plus进行升级

我把版本从:3.3.0 升级到了 3.4.3.2
启动项目的时候发现服务启动失败了,着急嘿~

然后在解决问题的过程中发现时因为jar包冲突了 。
然后发现了idea中一个很好使用的工具【在pom.xml文件中要,右击鼠标进入到Maven -> show dependence 】可以很直观的看见冲突法jar包,然后去解决对应的冲突就可以了 (这里不多说了,给大家一个学习链接传送门:https://blog.csdn.net/daerzei/article/details/82344569)

4.将原来的mybatis的插件配置调整成新版本的,并添加上动态表名的模块

4.1 调整mybatis plus 配置

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        //添加上自己实现的表名处理器DayRecordTableNameHandler
        dynamicTableNameInnerInterceptor.setTableNameHandler(new DayRecordTableNameHandler());
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);

        return interceptor;
    }

4.2 自定义表名称处理器

结合threadlocal 来确定对对应的业务逻辑使用什么表名称(我这里是利用将数据源信息放入到threadlocal中,然后来映射不同的表名称),下面的代码示例是一个简化版:

public class DayRecordTableNameHandler implements TableNameHandler {
    private static final Logger log = LoggerFactory.getLogger(DayRecordTableNameHandler.class);

    public DayRecordTableNameHandler(){
    }

    @Override
    public String dynamicTableName(String sql, String tableName) {
        Object dataSource = HnThreadLocal.get(SystemConstants.DATASOURCE);
        if(Objects.isNull(dataSource)){
            return tableName;
        }
        if(Objects.equals(tableName,"zsh_day_record")){
            int dataSourceIntValue = (int)dataSource;
            if(Objects.equals(dataSourceIntValue,1)){
                log.info("表名替换:"+tableName+"--->sql:ods_zsh_day_record_s");
                return "ods_zsh_day_record_s";
            }
        }
        return tableName;
    }

}

4.3 利用AOP切换数据源

这里想省略了,多数据源用的是dynamic-datasource-spring-boot-starter
AOP监听多是 @DS ,依据注解value来判断数据源是不是走doris

5.运行一下

成功运行

6. 需要注意的地方

  1. threadlocal 中的数据在aop中最好自己释放掉 ,spring是用的线程池,如果不清理掉会影响线程下次使用的程序
  2. 这是个草稿实现,因为前面强调的数据同步模块,是需要考虑进去的,继续摸索啦~~~

你可能感兴趣的:(mybatis,plus,mysql,数据库,java)