mybatis项目实现动态表名的三种方法

 更新时间:2024年01月19日 14:53:50   作者:沉默的旋律  
有时在开发过程中java代码中的表名和数据库的表名并不是一致的,此时我们就需要动态的设置表名,本文主要介绍了mybatis项目实现动态表名的三种方法,具有一定的参考价值,感兴趣的可以了解一下

实现动态表名是个很常见的需求,网上也有很多解决方法,这边总结了三种实现方式。

一、手动给每个方法加个表名的变量

缺点很明显,侵入性大,不方便,不推荐

二、mybatis插件机制拦截sql替换表名实现动态表名

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

/**
 * mybatis插件实现动态表名,可以拦截器新增、编辑、删除、查询等
 */
@Component
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {
                Connection.class, Integer.class})})
public class ReplaceTablePlugin implements Interceptor {

    private static final Logger LOG = LoggerFactory.getLogger(ReplaceTablePlugin.class);

    private final static Map<String, String> TABLE_MAP = new LinkedHashMap<>();

    /**
     * 需要替换的表(替换前的表名和替换后的表名)
     */
    static {
        TABLE_MAP.put("t_user", "t_user_20220101");
        TABLE_MAP.put("t_org", "t_org_20220202");
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        doTable(statementHandler, metaObject);
        return invocation.proceed();
    }

    private void doTable(StatementHandler handler, MetaObject metaStatementHandler) throws ClassNotFoundException {
        BoundSql boundSql = handler.getBoundSql();
        String originalSql = boundSql.getSql();
        if (originalSql != null && !originalSql.equals("")) {
            LOG.info("拦截前的sql:{}", originalSql);
            if (isReplaceTableName(originalSql)) {
                for (Map.Entry<String, String> entry : TABLE_MAP.entrySet()) {
                    originalSql = originalSql.replace(entry.getKey(), entry.getValue());
                }
                LOG.info("拦截后的sql:{}", originalSql);
                metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
            }
        }
    }

    private boolean isReplaceTableName(String sql) {
        for (String tableName : TABLE_MAP.keySet()) {
            if (sql.contains(tableName)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
    }

    /**
     * Obtain real processing objects, possibly multi-layer agents
     *
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T realTarget(Object target) {
        if (Proxy.isProxyClass(target.getClass())) {
            MetaObject metaObject = SystemMetaObject.forObject(target);
            return realTarget(metaObject.getValue("h.target"));
        }
        return (T) target;
    }
}

三、mybatis-plus的DynamicTableNameInnerInterceptor实现

3.1引入mybatis-plus的pom jar包依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-annotation</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-core</artifactId>
    <version>3.5.2</version>
</dependency>

3.2 实现的配置类

import java.util.Map;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.core.RedisTemplate;


/**
*
* mybatis-plus实现动态替换表名
*/
@MapperScan("com.xiaweiyi8080.dal.mapper")
@ComponentScan({"com.xiaweiyi8080.dal.manager"})
@Slf4j
public class MyBatisPlusConfiguration {

    @Autowired
    private RedisTemplate redisTemplate;

    // 配置文件里配置的哪些表需要动态表名
    @Value("${xxxxx.tableName:}")
    private String dynamicTableName;

    @Bean
    public MybatisPlusInterceptor dynamicTableNameInterceptor() {
        log.info("------拿到的dynamicTableName={}", dynamicTableName);
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            // 获取参数方法
            Map<String, Object> paramMap = RequestDataHelper.getRequestData();
            if (CollectionUtil.isNotEmpty(paramMap)) {
                paramMap.forEach((k, v) -> log.info(k + "----" + v));
            }
            if (StringUtils.isNotBlank(dynamicTableName) && dynamicTableName.contains(tableName)) {
                log.info("------替换前表名={}", tableName);
                String suffix = "_20220101";
                tableName += suffix;
                log.info("------替换后表名={}", tableName);
            }
            return tableName;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }

}

到此这篇关于mybatis项目实现动态表名的三种方法的文章就介绍到这了,更多相关mybatis 动态表名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring5中SpringWebContext方法过时的解决方案

    Spring5中SpringWebContext方法过时的解决方案

    这篇文章主要介绍了Spring5中SpringWebContext方法过时的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 在Mybatis中使用自定义缓存ehcache的方法

    在Mybatis中使用自定义缓存ehcache的方法

    这篇文章主要介绍了在Mybatis中使用自定义缓存ehcache的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • java实现坦克大战小游戏

    java实现坦克大战小游戏

    这篇文章主要为大家详细介绍了java实现坦克大战小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • 九个动画组图轮播总结全栈数据结构数组链表

    九个动画组图轮播总结全栈数据结构数组链表

    数据结构和算法是密不可分的,两者往往是相辅相成的存在,所以在学习数据结构过程中,不免会遇到各种算法,数据结构常用操作一般为:增删改查。基本上所有的数据结构都是围绕这几个操作进行展开,本文用九张动图来阐述先进后出的数据结构
    2021-08-08
  • Java8 LocalDateTime时间日期类使用实例详解

    Java8 LocalDateTime时间日期类使用实例详解

    本文从 LocalDateTime 类的创建、转换、格式化与解析、计算与比较以及其他操作几个方面详细介绍了 LocalDateTime 类在 Java 8 中的使用,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • Spring Boot整合Bootstrap的超详细步骤

    Spring Boot整合Bootstrap的超详细步骤

    之前做前端开发,在使用bootstrap的时候都是去官网下载,然后放到项目中,在页面引用,下面这篇文章主要给大家介绍了关于Spring Boot整合Bootstrap的超详细步骤,需要的朋友可以参考下
    2023-05-05
  • Java的super关键字与instanceof运算符使用方法

    Java的super关键字与instanceof运算符使用方法

    这篇文章主要介绍了Java的super关键字与instanceof运算符使用方法,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • SpringBoot可以同时处理多少请求流程分析

    SpringBoot可以同时处理多少请求流程分析

    SpringBoot默认的内嵌容器是Tomcat,也就是我们的程序实际上是运行在Tomcat里的,所以与其说SpringBoot可以处理多少请求,到不如说Tomcat可以处理多少请求,这篇文章主要介绍了SpringBoot可以同时处理多少请求,需要的朋友可以参考下
    2023-02-02
  • 解决Android Studio安装后运行出错dose not...和Internal error...

    解决Android Studio安装后运行出错dose not...和Internal error...

    这篇文章主要介绍了解决Android Studio安装后运行出错dose not...和Internal error...的相关资料,需要的朋友可以参考下
    2017-03-03
  • Maven的概述及基本使用示例详解

    Maven的概述及基本使用示例详解

    MApache Maven是一个项目管理和构建工具,它基于项目对象模型POM的概念,通过一小段描述信息来管理项目的构建、报告和文档,aven是专门用于管理和构建Java项目的工具,本文给大家介绍Maven的概述及基本使用,感兴趣的朋友一起看看吧
    2023-07-07

最新评论