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 这张表:

MyBatis-Plus(二十一)动态表名_第1张图片

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 这张表:

在这里插入图片描述

点击跳转至原文地址

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

在这里插入图片描述

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

你可能感兴趣的:(MyBatis-Plus)