您的位置:首页 > 编程语言 > Java开发

SpringBoot-JPA 支持分表

2018-01-23 17:05 671 查看
摘要: JPA Entity对象分表映射的一种方案

简介

- JPA Entity对象继承,通过@Inheritance配置,有三种方式SINGLE_TABLE、TABLE_PER_CLASS、JOINED,这里不作赘述。
- Entity对象的分库分表操作
- 分库,为了管理DB的连接数,建议通过入口的分流,将不同DB的数据分流到不同的应用;
- 分表,这是本文关注的主要问题,目标是调用JPA时不需要关心是否分表以及映射的规则,即分表对于Entity操作层是透明的;主要的步骤如下:
- 对象声明
- 实现JPA interceptor 拦截器
- 加载拦截器

对象声明

- 数据对象的基类,引入了@MappedSuperclass,如下面的样例

@MappedSuperclass
class UserBase {

@Id
private Long id;

private String name;

private int age;
... ...
}

- 数据对象,继承基类,使用[@Entity](https://my.oschina.net/u/1260961),如下面的样例

//模板表,用于JPA代码编写
@Entity
@Table(name = "t_user")
public class User extends UserBase { ... ...}

//id是0或者偶数的数据分表,用于配置了hibernate.ddl-auto时维护库表结构,不会出现在JPA相关代码中
@Entity
@Table(name = "t_user_0")
public class User0 extends UserBase { ... ...}

//与User0对应,id是奇数的数据分表
@Entity
@Table(name = "t_user_1")
public class User1 extends UserBase { ... ...}

// 数据对象操作类声明
public interface UserDao extends CrudRepository<User, Long> {}

JPA interceptor 拦截器

- 声明

import org.hibernate.EmptyInterceptor;

public class MyInterceptor extends EmptyInterceptor {

- 推荐使用ThreadLocal缓存业务对象类型和ID

static class Cached {
Class<?> clazz;
Serializable id;
Cached(Class<?> clazz, Serializable id) {
super();
this.clazz = clazz;
this.id = id;
}
... ... //自动生成的hashCode、equals方法
}

- 重载如下的方法onLoad、onSave、getEntity,调用ThreadLocal.set
- 重载onPrepareStatement方法,示意代码如下

Cached id = threadLocal.get();
threadLocal.remove();
if(id == null) {
return sql;
}
if(id.clazz == User.class) {
long offset = ((Long)id.id).longValue() / 2;
return sql.replace("t_user", "t_user_" + offset);
}

加载拦截器 Application.yml

spring:
jpa:
properties:
hibernate:
ejb:
interceptor: [拦截器类名]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  springboot jpa 分表