Id分表时间分表
Id分表注解
@Target({ ElementType.METHOD })
@Retention(RUNTIME)
@documented
public @interface VoteTenantId {
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 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);
}
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;
@Bean
@ConditionalOnMissingBean(MybatisPlusInterceptor.class)
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
HashMap 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;
}
}
方法处理
@Override
@VoteTenantId("{{#customerInfo.tenantId}}")
@Transactional(rollbackFor = Exception.class)
public void insert(CustomerInfo customerInfo) {
baseMapper.insert(customerInfo);
}
时间分表
实现·
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;
}
}



