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

2022-09-01 09:32:31 浏览数 (1)

  • 近日公司需要新框架需要兼容旧代码,旧代码用的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复制
}
  • 以上内容有错误欢迎指出~

0 人点赞