java通过注解实现分表详解

 更新时间:2024年11月08日 08:22:20   作者:LeoLi_4  
这篇文章主要为大家详细介绍了java如何通过注解实现分表,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下

写在前面

在业务开发中,需要根据不同的渠道存储产品销售信息,由于单个渠道数据量比较大,放在一个表中存储不合适,需要针对每个渠道单独存储。

代码实现

定义注解和切面

定义注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DynamicTable {
    /**
     * 需要分割的表名
     * @return
     */
    String tableName();

    /**
     * 后缀key
     * @return
     */
    String separateKey();
}

切面处理逻辑

@Aspect
@Component
@Slf4j
public class DynamicTableAspect {

    /**
     * 用于SpEL表达式解析.
     */
    private SpelExpressionParser parser = new SpelExpressionParser();
    /**
     * 用于获取方法参数定义名字.
     */
    private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();

    private static final String TABLE_NAME = "tableName";
    private static final String TABLE_SUFFIX = "tableSuffix";

    /**
     * 以注解为切点
     */
    @Pointcut("@annotation(com.leoli04.DynamicTable)")
    public void dynamicTable() {
    }

    @Around("dynamicTable()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if(method.isAnnotationPresent(DynamicTable.class)){
            DynamicTable dynamicTable =  (DynamicTable) method.getAnnotation(DynamicTable.class);
            String key = dynamicTable.separateKey();
            // 获取参数
            Object[] args = joinPoint.getArgs();

            Expression expression = parser.parseExpression(key);
            // 使用spring的DefaultParameterNameDiscoverer获取方法形参名数组
            String[] paramNames = nameDiscoverer.getParameterNames(method);
            // spring的表达式上下文对象
            EvaluationContext context = new StandardEvaluationContext();
            // 给上下文赋值
            for (int i = 0; i < args.length; i++) {
                context.setVariable(paramNames[i], args[i]);
            }

            RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
                put(TABLE_NAME, dynamicTable.tableName());
                put(TABLE_SUFFIX, expression.getValue(context));
            }});
            Object proceed = joinPoint.proceed();
            RequestDataHelper.removeRequestData();
            return proceed;
        }else{
            Object proceed = joinPoint.proceed();
            return proceed;
        }
    }

}

mybatis拦截器

上面代码在处理切面逻辑中有如下代码:

RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
                put(TABLE_NAME, dynamicTable.tableName());
                put(TABLE_SUFFIX, expression.getValue(context));
            }});
            
Object proceed = joinPoint.proceed();

RequestDataHelper.removeRequestData();

这段其实是在代码逻辑中设置了上下面,切面逻辑处理完了之后,再把上下文内容去除。目的是为了给mybatis拦截器使用当前请求的上下文内容。

拦截器内部利用的是是mubatis动态表名,内容如下:

@Configuration
@Slf4j
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());

        // 动态表名插件
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            // 获取参数方法
            Map<String, Object> paramMap = RequestDataHelper.getRequestData();
            if (CollectionUtils.isNotEmpty(paramMap)) {
                var tableNameParam = (String) paramMap.get("tableName");
                paramMap.forEach((k, v) -> log.info(k + "----" + v));
                if(tableNameParam.equals(tableName)){
                    // 获取传递的参数
                    String tableSuffix = (String) paramMap.get("tableSuffix");
                    if(StringUtils.isBlank(tableSuffix)){
                        return tableName;
                    }else{
                        // 组装动态表名
                        return tableName + "_" + tableSuffix;
                    }
                }
            }
            return tableName;
        });
        mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return mybatisPlusInterceptor;
    }
}

到此这篇关于java通过注解实现分表详解的文章就介绍到这了,更多相关java分表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇超详细的SpringBoot整合MybatisPlus的文章

    一篇超详细的SpringBoot整合MybatisPlus的文章

    这篇文章主要介绍了springboot整合Mybatis-plus的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • 详解SpringSecurity如何实现前后端分离

    详解SpringSecurity如何实现前后端分离

    这篇文章主要为大家介绍了详解SpringSecurity如何实现前后端分离,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Java实现Excel批量导入数据

    Java实现Excel批量导入数据

    这篇文章主要为大家详细介绍了Java实现Excel批量导入数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • Java图像处理工具类

    Java图像处理工具类

    这里给大家分享了一个java常用的图像处理工具类,包含缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等,有需要的小伙伴参考下。
    2015-02-02
  • Java设计模式之备忘录模式实现对象状态的保存和恢复

    Java设计模式之备忘录模式实现对象状态的保存和恢复

    本文介绍Java设计模式之备忘录模式,该模式可以实现对象状态的保存和恢复。通过详细讲解备忘录模式的原理、实现方法和应用场景,帮助读者深入理解该设计模式,并提供示例代码和技巧,便于读者实际应用
    2023-04-04
  • 深入浅析ArrayList 和 LinkedList的执行效率比较

    深入浅析ArrayList 和 LinkedList的执行效率比较

    这篇文章主要介绍了ArrayList 和 LinkedList的执行效率比较的相关资料,需要的朋友可以参考下
    2017-08-08
  • Java实现查找当前字符串最大回文串代码分享

    Java实现查找当前字符串最大回文串代码分享

    本文给大家介绍的是如何使用Java实现查找当前字符串最大回文串代码,非常的简单实用,有需要的小伙伴可以参考下
    2016-07-07
  • Stream distinct根据list某个字段去重的解决方案

    Stream distinct根据list某个字段去重的解决方案

    这篇文章主要介绍了Stream distinct根据list某个字段去重,stream的distinct去重方法,是根据 Object.equals,和 Object.hashCode这两个方法来判断是否重复的,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • Spring boot热部署devtools过程解析

    Spring boot热部署devtools过程解析

    这篇文章主要介绍了Spring boot热部署devtools过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • MyBatis批量插入的三种方式比较总结

    MyBatis批量插入的三种方式比较总结

    由于项目需要生成多条数据,并保存到数据库当中,所以就用到了MyBatis批量插入,下面这篇文章主要给大家介绍了关于MyBatis批量插入的三种方式的相关资料,需要的朋友可以参考下
    2021-08-08

最新评论