Spring Data Jpa 动态表处理
Jpa 分表问题
现在有一张学生表
t_stu
按年份进行了处理,物理表分别是
t_stu_2020
、
t_stu_2021
、
t_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;
@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插件,可以实现分表
properties:
hibernate:
# 注册自定义的插件类
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...
标签:
Java
,
数据库
,
中间件
,
Jpa
2024年 07月
2024年 04月
2024年 03月
2024年 02月
2024年 01月
2023年 12月
2023年 11月
2023年 10月
2023年 07月
2023年 06月
2023年 05月
2023年 04月
2023年 03月
2023年 02月
2023年 01月
2022年 09月
2022年 07月
2022年 06月
2022年 03月
2021年 12月
2021年 11月
2021年 10月
2021年 07月
2021年 04月
2021年 03月
2021年 02月
2021年 01月
2020年 12月
2020年 09月
2020年 04月
2020年 03月
2020年 02月
2020年 01月
2019年 10月
2019年 09月
2019年 08月
2019年 07月
2019年 06月
2019年 05月