MybatisPlus拦截器实现数据表分表

        很多项目都会存在一些数据量很大或者数据量增加很快的业务表,由于mysql的数据量达到一定量后会影响我们的查询效率,为了避免该类问题发生,我们需要在项目前期设计的时候针对这两类情况做一个分表的设计。这里的分表指的是水平拆分(只是表名不同,其余字段都一致,主键id不允许重复),对某一个数字取模运算做为拆分后表的后缀名,具体要分多少张表可通过自己实际的项目情况确定。

        首先创建请求参数传递的一个辅助类

/**
 * 请求参数传递辅助类
 */
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);
    }

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

        该辅助类主要作用有:

        a.设置请求参数
        b.将请求参数存取到线程变量中
        c.获取请求参数

        简单的说就是在涉及到需要分表的数据操作时,将请求参数放入线程变量中。然后在拦截器里面获取这个参数,做特定的处理,找到我们具体要操作的那张表。这里的请求参数大家可以把它理解成跟我们分表后的表名产生关联的数据。这里面的线程变量是仅在当前线程下可使用的数据,与其他线程做隔离。在本文中不做详细解释。

        在涉及到分表的数据层操作前(Mybatisplus或者Mybatis增删改查数据前),将请求参数放入线程变量

RequestDataHelper.setRequestData(Collections.singletonMap("studentId", param.getStudentId()));
        LambdaQueryWrapper<StudentRecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StudentRecordEntity::getStudentId, param.getStudentId());
        List<StudentRecordEntity> studentRecordEntityList = super.list(queryWrapper);

        Mybatisplus 拦截器代码

/**
     * Mybatis plus 拦截器
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        //动态表插件
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            // 获取参数方法
            if (tableName.equalsIgnoreCase("t_student_record")) {
                Map<String, Object> paramMap = RequestDataHelper.getRequestData();
                long studentId= Long.parseLong(String.valueOf(paramMap.get("studentId")));
                int mod = (int) (studentId% 16);
                return tableName + "_" + mod;

            } else {
                return tableName;
            }
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }

        这里面t_student_record表就是要拆分的表,如果有多个,在if里面写多个。studentId就是调用的时候传入线程变量的请求参数,对它%16就是分了16张表,根据实际业务情况,需要分多少张就把%后面的数字改为多少。

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 的基础上进行了扩展和增强,提供了更加便捷的 CRUD 操作、代码生成器等功能。MyBatis-Plus 也支持分表查询,具体实现方式如下: 1. 定义分表规则 在 MyBatis-Plus 中,我们可以通过自定义分表规则来实现分表查询。可以自定义一个分表策略类,用于根据查询条件生成对应的表名或分库分表信息。例如,我们可以定义一个以用户 ID 为分表依据的分表策略类: ```java public class UserTableShardStrategy implements IShardTableStrategy { @Override public String getTargetTableName(String tableName, Object params, String mapperId) { if (params == null) { throw new IllegalArgumentException("params can not be null."); } int userId = Integer.parseInt(params.toString()); int tableIndex = userId % 10; return tableName + "_" + tableIndex; } } ``` 这里我们将用户 ID 对 10 取模,得到一个在 0~9 范围内的数字,然后将分表后缀拼接到原表名后面,得到分表的表名。 2. 在实体类中定义分表字段 在实体类中,我们需要定义分表字段,用于指定分表规则的依据字段。例如,在 User 实体类中,我们可以定义一个 userId 字段来作为分表规则的依据。 ```java @Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; @TableField(value = "user_id", exist = true) private Integer userId; } ``` 这里我们使用了 `@TableField` 注解来标识 userId 字段对应的表字段名为 `user_id`,并且设置了 `exist=true`,表示该字段在数据库中存在。 3. 在 Mapper 中使用分表规则 在 Mapper 中,我们可以使用 MyBatis-Plus 的分表插件来实现分表查询。在 SQL 语句中,我们可以使用 `#{}` 占位符来引用分表参数。例如: ```xml <select id="getUserById" resultType="User"> SELECT * FROM user WHERE user_id = #{userId} </select> ``` 这里的 `#{userId}` 表示根据用户 ID 计算出分表后缀,然后将其拼接到 `user` 后面,得到最终的表名。 4. 注册分表插件 最后,我们需要在 MyBatis 的配置文件中注册分表插件,以便让 MyBatis-Plus 自动识别并处理分表查询语句。 ```xml <plugins> <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.inner.ShardTableInnerInterceptor"> <property name="shardTableStrategy" value="com.example.mybatisplusdemo.shard.UserTableShardStrategy"/> </plugin> </plugins> ``` 这里我们使用了一个 ShardTableInnerInterceptor 插件,它会在执行查询前根据分表规则自动修改 SQL 语句中的表名。需要注意的是,这里的 `com.example.mybatisplusdemo.shard.UserTableShardStrategy` 应该替换为你自己定义的分表策略类的全限定名。 以上就是使用 MyBatis-Plus 实现分表查询的基本步骤。需要注意的是,分表查询会增加系统的复杂度和维护难度,需要谨慎使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值