0
点赞
收藏
分享

微信扫一扫

MybatisPlus分表

小贴贴纸happy 2022-01-11 阅读 92

MybatisPlus分表

Id分表

  • 注解
@Target({ ElementType.METHOD })
@Retention(RUNTIME)
@Documented
public @interface VoteTenantId {

	/**
	 * 拦截方法之上,EL表达式
	 * @return EL表达式
	 */
	String value() default "";

}
  • 拦截器
@Component
@Aspect
public class VoteTenantIdAop {

	@Before(value = "@annotation(com.hccake.extend.mybatis.plus.annotation.VoteTenantId)")
	public void beforeCheckout(JoinPoint joinPoint) throws NoSuchMethodException {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = joinPoint.getTarget().getClass().getMethod(signature.getName(),
				signature.getMethod().getParameterTypes());
		VoteTenantId voteTenantId = method.getAnnotation(VoteTenantId.class);
		Object[] args = joinPoint.getArgs();
		String result = parseExpression(voteTenantId.value(), method, args);
		BaseIdDivideTableNameParser.setId(Integer.valueOf(result));
	}

	private String parseExpression(String expressionString, Method method, Object[] args) {
		// 获取被拦截方法参数名列表
		LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
		String[] paramNameArr = discoverer.getParameterNames(method);
		// SPEL解析
		ExpressionParser parser = new SpelExpressionParser();
		StandardEvaluationContext context = new StandardEvaluationContext();
		for (int i = 0; i < Objects.requireNonNull(paramNameArr).length; i++) {
			context.setVariable(paramNameArr[i], args[i]);
		}
		return parser.parseExpression(expressionString).getValue(context, String.class);
	}

}
  • 具体实现
public abstract class BaseIdDivideTableNameParser implements TableNameHandler {

	private static final ThreadLocal<Integer> ID = new ThreadLocal<>();

	public static void setId(Integer idValue) {
		ID.set(idValue);
	}

	@Override
	public String dynamicTableName(String sql, String tableName) {
		Integer table = ID.get();
		// 这里清除ThreadLocal的值,防止线程复用出现问题
		ID.remove();

		return tableName + tableName(table);
	}

	/**
	 * 划分分表规则,由子类实现
	 * @param tenantId tenantId
	 * @return tableName
	 */
	public abstract String tableName(Integer tenantId);

}
@Service
public class DivideTableName extends BaseIdDivideTableNameParser {

	@Override
	public String tableName(Integer tenantId) {
		return DivideRule.customerInfoRule(tenantId);
	}

}
  • 引用
@Component
@RequiredArgsConstructor
public class MybatisPlusInterceptorConfig {

	private final BaseIdDivideTableNameParser baseIdDivideTableNameParser;

	/**
	 * MybatisPlusInterceptor 插件,默认提供分页插件</br>
	 * 如需其他MP内置插件,则需自定义该Bean
	 * @return MybatisPlusInterceptor
	 */
	@Bean
	@ConditionalOnMissingBean(MybatisPlusInterceptor.class)
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
		DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
		HashMap<String, TableNameHandler> map = new HashMap<>(8);
		// 这里为不同的表设置对应表名处理器
		map.put("t_message_record", new TimeTableNameParser());
		map.put("t_customer_info", baseIdDivideTableNameParser);
		dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
		interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
		return interceptor;
	}

}

时间分表

  • 实现·
public class TimeTableNameParser implements TableNameHandler {

	@Override
	public String dynamicTableName(String sql, String tableName) {
		LocalDate date = LocalDate.now();
		String table = "_" + date.format(DateTimeFormatter.ofPattern("yyyy_MM"));
		return tableName + table;
	}

}
举报

相关推荐

0 条评论