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分表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java全能工具类之Hutool的用法详解

    Java全能工具类之Hutool的用法详解

    Hutool是一个Java工具类库,由国内的程序员loolly开发,目的是提供一些方便、快捷、实用的工具类和工具方法,本文就来详细聊聊它的使用吧
    2023-03-03
  • java使用EasyExcel导入导出excel

    java使用EasyExcel导入导出excel

    导入导出excel数据是常见的需求,今天就来看一下Java基于EasyExcel实现这个功能,感兴趣的朋友可以了解下
    2021-05-05
  • java实现读取带合并单元格的Excel

    java实现读取带合并单元格的Excel

    这篇文章主要为大家详细介绍了java如何实现读取带合并单元格的Excel,文中的示例代码讲解详细, 感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • 详解在Spring Boot中使用Https

    详解在Spring Boot中使用Https

    本篇文章主要介绍了详解在Spring Boot中使用Https,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • java实现电脑端扫描二维码

    java实现电脑端扫描二维码

    这篇文章主要为大家详细介绍了java实现电脑端扫描二维码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Spring context:component-scan的使用及说明

    Spring context:component-scan的使用及说明

    这篇文章主要介绍了Spring context:component-scan的使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 关于springboot 配置date字段返回时间戳的问题

    关于springboot 配置date字段返回时间戳的问题

    这篇文章主要介绍了springboot 配置date字段返回时间戳的问题,在springboot2.0后,spring会将Date字段自动给转成UTC字符串了(在没有配置的情况下),所以date需要转换成时间戳还是yyyy-MM-dd HH:mm:ss,具体解决方法跟随小编一起看看吧
    2021-07-07
  • 微服务分布式架构实现日志链路跟踪的方法

    微服务分布式架构实现日志链路跟踪的方法

    在现有的系统中,由于大量的其他用户/其他线程的日志也一起输出穿行其中导致很难筛选出指定请求的全部相关日志。那我们如何来处理呢?带着这个问题一起通过本文学习下吧
    2021-08-08
  • JAVA中使用openoffice将Excel转PDF再转图片功能的实现代码

    JAVA中使用openoffice将Excel转PDF再转图片功能的实现代码

    这篇文章主要介绍了JAVA中使用openoffice将Excel转PDF再转图片功能实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • JSqlParse完整介绍

    JSqlParse完整介绍

    JSqlParse是一款很精简的sql解析工具,本文主要介绍了JSqlParse完整介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05

最新评论