前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mybatis-Plus 动态表名3.4.3.4,3.4,3.1.2

Mybatis-Plus 动态表名3.4.3.4,3.4,3.1.2

原创
作者头像
fate急速出击
发布2022-09-01 09:32:31
8880
发布2022-09-01 09:32:31
举报
文章被收录于专栏:springboot1springboot1
  • 近日公司需要新框架需要兼容旧代码,旧代码用的mybatis手写的动态表名 ,大概是实体类定义一个table字段 然后将table的值传到映射文件中,${table} 这种方式, 研究了一下mp发现可以直接用拦截器替换表名就有了以下代码

1. 3.4.3.4 (最新版)动态表名实现

1.配置类 (官方方式)

代码语言:java
复制
@Configuration
@MapperScan("com.cars.ysdd.clts.domain.clts.dao")
public class MybatisPlusConfig {

    static List<String> tableList(){
        List<String> tables = new ArrayList<>();
        tables.add("user");
        return tables;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            // 获取参数方法
            /*Map<String, Object> paramMap = RequestDataHelper.getRequestData();
            paramMap.forEach((k, v) -> System.err.println(k + "----" + v));

            System.err.println("表名:"+tableName);
            System.err.println("sql:"+sql);
            String year = "_2018";
            int random = new Random().nextInt(10);
            if (random % 2 == 1) {
                year = "_2019";
            }*/
            String newTable = null;
            for (String table : tableList()) {
                newTable = RequestDataHelper.getRequestData(table);
                if (table.equals(tableName) && newTable!=null){
                    tableName = newTable;
                    break;
                }
            }
            return tableName;
//            return tableName + year;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        // 3.4.3.2 作废该方式
        // dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
        return interceptor;
    }
}

2.请求参数传递辅助类

代码语言:java
复制
package com.baomidou.mybatisplus.samples.dytablename.config;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.Map;

/**
 * 请求参数传递辅助类
 */
public class RequestDataHelper {
    /**
     * 请求参数存取
     */
    private static final ThreadLocal<Map<String, Object>> REQUEST_DATA = new ThreadLocal<>();

    /**
     * 设置请求参数
     *
     * @param requestData 请求参数 MAP 对象
     */
    public static void setRequestData(Map<String, Object> requestData) {
        REQUEST_DATA.set(requestData);
    }

    /**
     * 获取请求参数
     *
     * @param param 请求参数
     * @return 请求参数 MAP 对象
     */
    public static <T> T getRequestData(String param) {
        Map<String, Object> dataMap = getRequestData();
        if (CollectionUtils.isNotEmpty(dataMap)) {
            return (T) dataMap.get(param);
        }
        return null;
    }

    /**
     * 获取请求参数
     *
     * @return 请求参数 MAP 对象
     */
    public static Map<String, Object> getRequestData() {
        return REQUEST_DATA.get();
    }
}

3.使用

代码语言:java
复制
@SpringBootTest
class DynamicTableNameTest {
    @Resource
    private UserMapper userMapper;

    @Test
    void test() {
        
        RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
            put("user", "user_2018");
        }});


        // 自己去观察打印 SQL 目前随机访问 user_2018  user_2019 表
        for (int i = 0; i < 6; i++) {
            User user = userMapper.selectById(1);
            System.err.println(user.getName());
        }
    }
}

2. 3.4.1版

1. 配置类

  • 这里的RequestDataHelper 用的是上文的3.4.3.4中的@Configuration @MapperScan("com.cars.ysdd.clts.domain.clts.dao") public class DynamicTableNameHandler { static List<String> tableList() { List<String> tables = new ArrayList<>(); tables.add("CR_CZJM"); return tables; } @Bean public MybatisPlusInterceptor paginationInterceptor() { MybatisPlusInterceptor paginationInterceptor = new MybatisPlusInterceptor(); // DynamicTableNameParser 表名解析器,动态解析表名,ITableNameHandler 表名处理。 DynamicTableNameInnerInterceptor dynamicTableNameParser = new DynamicTableNameInnerInterceptor(); dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, TableNameHandler>(2) {{ //metaObject 元对象 ;sql 执行的SQL ;tableName 表名 //这里put的key就是需要替换的原始表名,也就是实体类的表名 //这里的tableName就是我们定义的动态表名变量, for (String table : tableList()) { put(table, (sql, tableName) -> { // 获取传入参数 tableName,tableName的值就是替换后的表名 return RequestDataHelper.getRequestData(table) == null ? tableName : RequestDataHelper.getRequestData(table); }); } }}); paginationInterceptor.addInnerInterceptor(dynamicTableNameParser); return paginationInterceptor; } }2. 使用/** * @param crCzjmDO 实体类 * @return 执行条数 */ @Override public int insert(CrCzjmDO crCzjmDO) { RequestDataHelper.setRequestData(new HashMap<String, Object>(){{ put("CR_CZJM","TJFX.CR_CZJM"); }}); return crCzjmMapper.insertSelective(crCzjmDO); }

3. 3.4 以下版本 (3.1.2 版为例)

1.配置类

代码语言:java
复制
@Configuration
public class DynamicTableNameHandler {


    /**
     * 适用于相同表结构 不同表名
     */

    //实体类对应的表名字段
    public static final String DYNAMIC_TABLE_NAME = "tableName";

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // DynamicTableNameParser 表名解析器,动态解析表名,ITableNameHandler 表名处理。
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
            //metaObject 元对象 ;sql 执行的SQL ;tableName 表名
            //这里put的key就是需要替换的原始表名,也就是实体类的表名
            //这里的tableName就是我们定义的动态表名变量,
            put("payment", (metaObject, sql, tableName) -> {
                // 获取传入参数 tableName,tableName的值就是替换后的表名
                Object param = getParamValue(DYNAMIC_TABLE_NAME, metaObject);
                if(param == null){
                    return tableName;//不带tableName参数就返回原表名
                }else {
                    return param.toString();//带tableName参数就返回新表名
                }
            });
            /*put("payment", (metaObject, sql, tableName) -> {
                // 获取传入参数 tableName,tableName的值就是替换后的表名
                Object param = getParamValue(DYNAMIC_TABLE_NAME, metaObject);
                if(param == null){
                    return tableName;//不带tableName参数就返回原表名
                }else {
                    return param.toString();//带tableName参数就返回新表名
                }
            });*/
        }});
        paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));
        return paginationInterceptor;
    }

    /**
     * 获取动态表tableName参数的值
     */
    private Object getParamValue(String title, MetaObject metaObject){
        //获取参数
        Object originalObject = metaObject.getOriginalObject();
        JSONObject originalObjectJSON = JSON.parseObject(JSON.toJSONString(originalObject));
        JSONObject boundSql = originalObjectJSON.getJSONObject("boundSql");
        try {
            JSONObject parameterObject = boundSql.getJSONObject("parameterObject");
            return parameterObject.get(title);
        }catch (Exception e) {
            return null;
        }
    }
}

2. 实体类示例

  • 定义一个与上边配置类中DYNAMIC_TABLE_NAME 的值对应名称的字段(非数据库
代码语言:java
复制
@Data
public class Payment implements Serializable {

    private static final long serialVersionUID = 1L;

    private String serial;

    @TableField(exist = false)
    private String tableName;
}

3. 使用

  • 直接setTableName即可
代码语言:txt
复制
@Override
代码语言:txt
复制
public List<Payment> selectByTable(String table) {
代码语言:txt
复制
    Payment payment = new Payment();
代码语言:txt
复制
    payment.setTableName(table);
代码语言:txt
复制
    return paymentMapper.select(payment);
代码语言:txt
复制
}
  • 以上内容有错误欢迎指出~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 3.4.3.4 (最新版)动态表名实现
    • 1.配置类 (官方方式)
      • 2.请求参数传递辅助类
        • 3.使用
        • 2. 3.4.1版
          • 1. 配置类
          • 3. 3.4 以下版本 (3.1.2 版为例)
            • 1.配置类
              • 2. 实体类示例
                • 3. 使用
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档