SpringBoot-JPA 支持分表

简介

- 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: [拦截器类名]
相关文章
相关标签/搜索