Spring Boot分表查询实战指南
问题背景
在Spring Boot + MyBatis项目中,数据分表(如按月分表、按业务分表)是常见的优化手段。但分表后,前端如何根据条件动态映射到对应的子表查询数据成为技术难点。需要解决动态表名、条件路由、查询结果合并等问题。
解决方案一:动态表名拼接
通过MyBatis的动态SQL功能,在Mapper层根据前端传入的参数动态拼接表名。适用于分表规则明确(如按日期、ID范围分表)的场景。
<!-- Mapper XML示例 -->
<select id="selectByCondition" resultType="YourEntity">
SELECT * FROM ${tablePrefix}_${suffix}
WHERE 1=1
<if test="condition1 != null">
AND condition1 = #{condition1}
</if>
</select>
关键点:
- 使用
${}而非#{}直接拼接表名(需注意SQL注入风险) - 表名前缀(如
order_2023)和后缀(如月份)由前端或服务端逻辑生成
解决方案二:抽象路由层
通过中间路由层(如AOP或自定义注解)实现表名动态切换,保持业务代码与分表逻辑解耦。
// 自定义注解示例
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableRouter {
String key() default "createTime"; // 路由字段
String pattern() default "yyyyMM"; // 分表规则
}
// AOP切面实现动态表名切换
@Around("@annotation(router)")
public Object routeTable(ProceedingJoinPoint joinPoint, TableRouter router) {
String tableName = calculateTableName(router);
RequestContext.setCurrentTable(tableName); // 线程上下文传递表名
return joinPoint.proceed();
}
实现步骤:
- 定义分表规则(如按用户ID哈希取模)
- 通过拦截器或AOP在查询前动态设置表名
- MyBatis通过
<if test="currentTable != null">使用动态表名
解决方案三:分库分表中间件
集成ShardingSphere等分库分表中间件,通过配置实现透明化分表查询。
# ShardingSphere配置示例
spring:
shardingsphere:
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds.t_order_$->{2020..2023}_$->{1..12}
table-strategy:
standard:
sharding-column: create_time
precise-algorithm-class-name: com.example.TimePreciseShardingAlgorithm
优势:
- 自动路由到正确子表
- 支持跨表查询结果合并
- 内置分布式事务支持
前端协作方案
-
参数透传
前端传递分表关键字段(如用户ID、日期范围),后端根据字段值计算目标表。 -
约定式分表
前后端约定分表命名规则(如order_<user_id%10>),减少动态计算开销。 -
元数据接口
提供/tables/metadata接口返回可用表名列表,供前端筛选条件使用。
注意事项
-
SQL注入防护
动态表名需白名单校验或加密哈希处理,避免${}直接拼接用户输入。 -
跨表查询性能
避免无条件全表扫描,分页查询需特殊处理(如ShardingSphere的归并查询)。 -
事务一致性
跨表操作需考虑分布式事务,可使用@ShardingTransactionType注解。
扩展优化
-
缓存表路由结果
对高频访问的分表键(如用户ID)缓存表名映射关系。 -
虚拟表视图
数据库层创建视图统一查询入口,如CREATE VIEW order_all AS SELECT * FROM order_1 UNION ALL...。 -
异步预计算
通过定时任务预计算分表路由关系,生成路由表供快速查询。
通过上述方案,可灵活实现分表场景下的条件映射查询,同时保持代码的可维护性和扩展性。
BbS.okapop153.sbs/PoSt/1122_548553.HtM
BbS.okapop154.sbs/PoSt/1122_744087.HtM
BbS.okapop155.sbs/PoSt/1122_647133.HtM
BbS.okapop156.sbs/PoSt/1122_651647.HtM
BbS.okapop157.sbs/PoSt/1122_267644.HtM
BbS.okapop158.sbs/PoSt/1122_193437.HtM
BbS.okapop159.sbs/PoSt/1122_890817.HtM
BbS.okapop160.sbs/PoSt/1122_287443.HtM
BbS.okapop161.sbs/PoSt/1122_595408.HtM
BbS.okapop162.sbs/PoSt/1122_752922.HtM
BbS.okapop153.sbs/PoSt/1122_920365.HtM
BbS.okapop154.sbs/PoSt/1122_614571.HtM
BbS.okapop155.sbs/PoSt/1122_516853.HtM
BbS.okapop156.sbs/PoSt/1122_665508.HtM
BbS.okapop157.sbs/PoSt/1122_190023.HtM
BbS.okapop158.sbs/PoSt/1122_818099.HtM
BbS.okapop159.sbs/PoSt/1122_484352.HtM
BbS.okapop160.sbs/PoSt/1122_262981.HtM
BbS.okapop161.sbs/PoSt/1122_286219.HtM
BbS.okapop162.sbs/PoSt/1122_136638.HtM
BbS.okapop153.sbs/PoSt/1122_873153.HtM
BbS.okapop154.sbs/PoSt/1122_225231.HtM
BbS.okapop155.sbs/PoSt/1122_928299.HtM
BbS.okapop156.sbs/PoSt/1122_658096.HtM
BbS.okapop157.sbs/PoSt/1122_684025.HtM
BbS.okapop158.sbs/PoSt/1122_715200.HtM
BbS.okapop159.sbs/PoSt/1122_244126.HtM
BbS.okapop160.sbs/PoSt/1122_487646.HtM
BbS.okapop161.sbs/PoSt/1122_260619.HtM
BbS.okapop162.sbs/PoSt/1122_782755.HtM
BbS.okapop153.sbs/PoSt/1122_989371.HtM
BbS.okapop154.sbs/PoSt/1122_683772.HtM
BbS.okapop155.sbs/PoSt/1122_998267.HtM
BbS.okapop156.sbs/PoSt/1122_821985.HtM
BbS.okapop157.sbs/PoSt/1122_987351.HtM
BbS.okapop158.sbs/PoSt/1122_777020.HtM
BbS.okapop159.sbs/PoSt/1122_699794.HtM
BbS.okapop160.sbs/PoSt/1122_880837.HtM
BbS.okapop161.sbs/PoSt/1122_508199.HtM
BbS.okapop162.sbs/PoSt/1122_490887.HtM
BbS.okapop153.sbs/PoSt/1122_152457.HtM
BbS.okapop154.sbs/PoSt/1122_853754.HtM
BbS.okapop155.sbs/PoSt/1122_744941.HtM
BbS.okapop156.sbs/PoSt/1122_618875.HtM
BbS.okapop157.sbs/PoSt/1122_809244.HtM
BbS.okapop158.sbs/PoSt/1122_617422.HtM
BbS.okapop159.sbs/PoSt/1122_340495.HtM
BbS.okapop160.sbs/PoSt/1122_999094.HtM
BbS.okapop161.sbs/PoSt/1122_592823.HtM
BbS.okapop162.sbs/PoSt/1122_446887.HtM
BbS.okapop153.sbs/PoSt/1122_070567.HtM
BbS.okapop154.sbs/PoSt/1122_182618.HtM
BbS.okapop155.sbs/PoSt/1122_229412.HtM
BbS.okapop156.sbs/PoSt/1122_838196.HtM
BbS.okapop157.sbs/PoSt/1122_102209.HtM
BbS.okapop158.sbs/PoSt/1122_607409.HtM
BbS.okapop159.sbs/PoSt/1122_208962.HtM
BbS.okapop160.sbs/PoSt/1122_108975.HtM
BbS.okapop161.sbs/PoSt/1122_630598.HtM
BbS.okapop162.sbs/PoSt/1122_051369.HtM
BbS.okapop153.sbs/PoSt/1122_897778.HtM
BbS.okapop154.sbs/PoSt/1122_119675.HtM
BbS.okapop155.sbs/PoSt/1122_111751.HtM
BbS.okapop156.sbs/PoSt/1122_520501.HtM
BbS.okapop157.sbs/PoSt/1122_852099.HtM
BbS.okapop158.sbs/PoSt/1122_034328.HtM
BbS.okapop159.sbs/PoSt/1122_612303.HtM
BbS.okapop160.sbs/PoSt/1122_692032.HtM
BbS.okapop161.sbs/PoSt/1122_774594.HtM
BbS.okapop162.sbs/PoSt/1122_818075.HtM
BbS.okapop153.sbs/PoSt/1122_548817.HtM
BbS.okapop154.sbs/PoSt/1122_779277.HtM
BbS.okapop155.sbs/PoSt/1122_957916.HtM
BbS.okapop156.sbs/PoSt/1122_773002.HtM
BbS.okapop157.sbs/PoSt/1122_644096.HtM
BbS.okapop158.sbs/PoSt/1122_249718.HtM
BbS.okapop159.sbs/PoSt/1122_500441.HtM
BbS.okapop160.sbs/PoSt/1122_436955.HtM
BbS.okapop161.sbs/PoSt/1122_778501.HtM
BbS.okapop162.sbs/PoSt/1122_611016.HtM
查看11道真题和解析