ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Data Jpa 分表处理

2022-07-19 11:00:06  阅读:187  来源: 互联网

标签:插件 String stu Jpa Spring 表处理 schoolYear sql public


Spring Data Jpa 动态表处理

Jpa 分表问题

现在有一张学生表t_stu按年份进行了处理,物理表分别是t_stu_2020t_stu_2021t_stu_2022这样

如果是mybatis,可以直接把表后缀传入sql,然后使用t_stu_${year}对表名进行拼接

但是对于Jpa这个全自动化ORM框架来说不太好处理,因为Jpa的表名是写在实体类的注解上的,在运行时不能修改:

// 实体类
@Entity
@Table(name = "t_stu") // 这里的表名定义是无法在运行时修改的
@Getter
@Setter
public class TVisionStu {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    private String id;
    
    @Column(name = "name")
    private String name;
}

// dao 层
@Repository
public interface TVisionStuDao extends JpaRepository<TVisionStu, String>, JpaSpecificationExecutor<TVisionStu> {}

解决方案

Hibernate 插件方式

Hibernate 插件可以在sql执行前对sql进行修改,从而达到动态表的功能

import org.apache.commons.lang3.StringUtils;
import org.hibernate.EmptyInterceptor;
import org.springframework.stereotype.Component;

@Component
public class HibernateInterceptor extends EmptyInterceptor {
    @Override
    public String onPrepareStatement(String sql) {
        String schoolYear = ReqContextHolder.getSchoolYear();

        // 这里对表名进行替换
        if (StringUtils.isNotBlank(schoolYear)) {
            return sql.replaceAll("t_stu", "t_stu_" + schoolYear);
        }

        return super.onPrepareStatement(sql);
    }
}

其中的ReqContextHolder是一个线程安全的类,用来保存要查找的实际年份

public class ReqContextHolder {
    private ReqContextHolder() {
    }

    protected static ThreadLocal<String> schoolYearThreadLocal = new ThreadLocal<>();

    public static void setSchoolYear(String schoolYear) {
        schoolYearThreadLocal.set(schoolYear);
    }

    public static String getSchoolYear() {
        return schoolYearThreadLocal.get();
    }
    
    public static void remove() {
        schoolYearThreadLocal.remove();
    }
}

然后在application.yml中对插件进行配置:

spring:
  # 设置jpa插件,可以实现分表
  jpa:
    properties:
      hibernate:
        ejb:
          # 注册自定义的插件类
          interceptor: com.power.aop.HibernateInterceptor

实际使用的话就像这样:


@RestController
@RequestMapping("/stu")
public class StuController{
    
    @GetMapping("/query")
    public List<TVisionStu> query(@RequestParam("schoolYear") String schoolYear) {
        ReqContextHolder.setSchoolYear(schoolYear);
        List<TVisionStu> list = this.stuDao.findAll();
        ReqContextHolder.remove();
        return list;
    }
}

然后就可以到sql可以正常执行了。

如果觉得每个方法都需要设置学年非常麻烦,可以写一个拦截器进行处理,这里就不再赘述了。

sharding jdbc 方式

sharding sphere 是专门解决分库分表问题的,不用写Hibernate插件这种比较hack的方式,只需要引入一个jdbc的jar包然后进行配置就行了

To Be Continued...

标签:插件,String,stu,Jpa,Spring,表处理,schoolYear,sql,public
来源: https://www.cnblogs.com/lixin-link/p/16493274.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有