MyBatis-Plus(二十一)动态表名

动态表名

1、业务场景

  1. 有时我们希望存储或读取数据的时候能够根据情况、或根据传入参数来动态的选择对应的表。比如我们数据库里的用户信息表通过年份拆分(使用年份做后缀)

在这里插入图片描述

  1. 而对应的实体类是不包含年份后缀的:
@Data
public class UserInfo {
    private Integer id;
    private String userName;
    private String passWord;
    private Integer age;
}

2、样例代码

  1. 首先我们实现 ITableNameHandler 接口注入到 DynamicTableNameParser 处理器链中,将动态表名解析器注入到 MP 解析链(这里我们获取当前年份作为 user_info 表后缀)。

提示:动态表名的原理就是解析替换设定表名为处理器的返回表名

@Configuration
public class MybatisPlusConfig {
 
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
            put("user_info", (metaObject, sql, tableName) -> {
                // metaObject 可以获取传入参数,这里实现你自己的动态规则
                // 这里我使用当前年份做后缀
                int year = Calendar.getInstance().get(Calendar.YEAR);
                return tableName + "_" + year;
            });
        }});
        paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));
        return paginationInterceptor;
    }
}
  1. 然后开始查询数据:
@RestController
public class HelloController {
 
    @Autowired
    UserInfoMapper userInfoMapper;
 
    @GetMapping("/test")
    public List<UserInfo> test() {
        return userInfoMapper.selectList(null);
    }
}
  1. 查看控制台日志可以发现实际查询的是 user_info_2020 这张表:

在这里插入图片描述

3、根据参数来动态选择对应的表

  1. 这里我们对动态表名解析器代码稍作修改,根据传入的参数 year 来动态决定使用的数据表:
    • 比如当 year 参数为 2019 则使用 user_info_2019 这张表。
    • 如果没有 year 参数则使用当前年份做后缀,比如 user_info_2020
@Configuration
public class MybatisPlusConfig {
 
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
            put("user_info", (metaObject, sql, tableName) -> {
                // 获取传入参数 year,如果有的话做为后缀,没有的话则使用当前年份作为后缀
                Object param = getParamValue("year", metaObject);
                String year = param !=null ? String.valueOf(param)
                        : String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
                return tableName + "_" + year;
            });
        }});
        paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));
        return paginationInterceptor;
    }
 
    /**
     * 获取参数值
     */
    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;
        }
    }
}
  1. 修改 UserInfoMapper 接口,在定义方法中添加 year 参数:

注意:如果方法只有一个参数必须添加 @Param 注解,否则动态表名解析器中无法通过参数名获取对应的值。

public interface UserInfoMapper extends BaseMapper<UserInfo> {
    @Select("select * from user_info")
    List<UserInfo> getAll(@Param("year") int year);
}
  • 如果方法有多个参数的话,可以不用添加 @Param 注解:
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    @Select("select * from user_info")
    List<UserInfo> getAll(int year, int month);
}
  1. 我们调用这个 Mapper 查询时传入一个指定年份,比如 2019
@RestController
public class HelloController {
 
    @Autowired
    UserInfoMapper userInfoMapper;
 
    @GetMapping("/test")
    public List<UserInfo> test() {
        return userInfoMapper.getAll(2019);
    }
}
  1. 查看控制台日志可以发现实际查询的是 user_info_2019 这张表:

在这里插入图片描述

点击跳转至原文地址

--------------最后感谢大家的阅读,愿大家技术越来越流弊!--------------

在这里插入图片描述

--------------也希望大家给我点支持,谢谢各位大佬了!!!--------------

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MyBatis-Plus是一个基于MyBatis的增强工具,它提供了许多方便的功能,其中包括动态表名的支持。通过使用MyBatis-Plus提供的DynamicTableNameInnerInterceptor拦截器,可以在运行时动态替换SQL语句中的表名。 使用MyBatis-Plus实现动态表名有以下几个作用: 1. 实现数据分表或数据分区:可以根据特定的规则生成动态表名,例如按照时间分表或按照业务冷热数据分离后将数据存储在不同的表中。 2. 隐藏数据表名:在某些情况下,为了安全或其他目的,可能需要隐藏数据库表名。使用DynamicTableNameInnerInterceptor可以将表名进行动态替换,从而达到隐藏表名的效果。 3. 提高系统的可扩展性:通过动态表名解析器,可以将不同的数据表或数据库实例进行解耦,从而提高系统的可扩展性。例如,可以将一个大型的数据库系统分成多个小型的数据库实例,然后通过动态表名解析器将SQL语句分发到不同的实例中。 4. 简化代码开发:使用DynamicTableNameInnerInterceptor,可以避免在代码中硬编码SQL语句中的表名,从而简化代码的开发和维护。特别是在应对表结构频繁变化的场景下,使用该拦截器能够更快速地实现表名变更,从而降低维护成本。 因此,通过使用MyBatis-Plus的DynamicTableNameInnerInterceptor拦截器,可以实现mybatis-plus动态表名的功能,并带来诸多好处。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【mybatis-plus系列】动态表名](https://blog.csdn.net/qyj19920704/article/details/130010294)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [mybatis-plus动态表名实现](https://blog.csdn.net/zhangsuhua0702/article/details/122807303)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值