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: [攔截器類名]
相關文章
相關標籤/搜索