You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ShardingSphere集成SpringBoot时如何按角色查询指定分片表

实现方案

两种可行的实现路径,根据你的项目情况选择即可:

方案一:自定义分片策略+线程上下文传参(推荐,无业务侵入)

  • 第一步:全局透传当前用户角色
    用ThreadLocal封装上下文工具类,在请求拦截器中注入当前登录用户的角色,请求结束后清除避免线程复用污染:
    public class UserContextHolder {
        private static final ThreadLocal<String> USER_ROLE = new ThreadLocal<>();
    
        public static void setRole(String role) {
            USER_ROLE.set(role);
        }
    
        public static String getRole() {
            return USER_ROLE.get();
        }
    
        public static void clear() {
            USER_ROLE.remove();
        }
    }
    
  • 第二步:实现自定义分表路由算法
    实现ShardingSphere的PreciseShardingAlgorithm接口,路由逻辑直接读取上下文中的角色返回对应实际表:
    public class OrderRoleShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
        @Override
        public String doSharding(Collection<String> availableTables, PreciseShardingValue<Long> shardingValue) {
            String role = UserContextHolder.getRole();
            // 测试角色固定路由到order_1
            if ("TEST".equals(role)) {
                return "order_1";
            }
            // 普通用户默认路由到order_0
            return "order_0";
        }
    }
    
  • 第三步:修改ShardingSphere配置关联自定义算法
    以yml配置为例:
    spring:
      shardingsphere:
        rules:
          sharding:
            tables:
              order:
                actual-data-nodes: 你的数据源名.order_$->{0..1}
                table-strategy:
                  standard:
                    sharding-column: user_id # 随便填一个order表中存在的字段即可,算法中不会用到该字段值
                    sharding-algorithm-name: order-role-alg
            sharding-algorithms:
              order-role-alg:
                type: CLASS_BASED
                props:
                  strategy: standard
                  algorithm-class-name: 你项目的全类名.OrderRoleShardingAlgorithm
    

方案二:Hint强制路由(适合不想修改原有分片规则的场景)

直接用切面拦截所有order表的查询操作,根据角色用ShardingSphere的HintManager强制指定路由表,完全不影响原有分片逻辑:

// 查询前设置路由规则
@Before("execution(* com.xxx.mapper.OrderMapper.select*(..))")
public void setOrderRoute() {
    HintManager hintManager = HintManager.getInstance();
    String role = UserContextHolder.getRole();
    if ("TEST".equals(role)) {
        hintManager.addTableShardingValue("order", 1);
    } else {
        hintManager.addTableShardingValue("order", 0);
    }
}

// 查询结束清除路由规则
@After("execution(* com.xxx.mapper.OrderMapper.select*(..))")
public void clearOrderRoute() {
    HintManager.clear();
}

注意事项

  • 必须在请求拦截器的afterCompletion方法中调用UserContextHolder.clear(),避免服务端线程池复用导致角色串用
  • 异步查询场景需要手动把角色传递到异步线程,ThreadLocal默认不支持跨线程传值
  • 要求高安全性的场景可以额外加MyBatis拦截器校验,测试角色的查询语句如果出现order_0直接抛出权限异常

内容的提问来源于stack exchange,提问作者rellocs wood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 04:09:04