Spring Boot JPA:将一个实体映射到具有相同列的多个(很多)表
Posted
技术标签:
【中文标题】Spring Boot JPA:将一个实体映射到具有相同列的多个(很多)表【英文标题】:Spring Boot JPA: Mapping one entity to multiple (a lot) tables with same columns 【发布时间】:2020-10-26 22:15:47 【问题描述】:我有很多(比如 60 多个)具有相同架构和相似名称的表:
log_2020_07_01
log_2020_07_02
... and so on.
它们具有相同的列:id, site, size
。每个表包含大约 200 万行。
我读过Hibernate and tables with same data/columns but with different table names,它建议单独使用hibernate。我希望七年后我们可以用 JPA 做一些新的事情。
在JPA中,是否可以只写一个实体类,让代码来处理使用哪个表?
例如,
for(int i=0;i<60;i++)
// read from the i-th table.
【问题讨论】:
特别是对此的评论:我希望七年后我们可以用 JPA 做一些新的事情。为什么有人会努力处理所有可能的不良设计?所以我不会屏住呼吸等待这个解决方案。有一个真正的解决方法,但它要求有人停止生成这些表,并且有人愿意做一些数据库表迁移。 @pirho 水平数据库分片不是一个糟糕的设计。 我是不是这么说的:) 你在解决与水平分片相关的问题吗?这些表是否位于多个数据库服务器中?好吧,我想实施它的方法有好有坏,没有严格的标准。很少有链接here。一眼看去,这些扩展并没有流行起来,当然也不使用表名来散列服务器周围的行。 Ex. of using Hibernate shards。猜猜也不允许不同的表名 @pirho 我添加了一个拦截器来根据需要动态更改表名。将尝试您提供的分片链接。 希望你设法让它工作。如果你这样做了,请提供你的解决方案作为答案,期待看到它。 【参考方案1】:首先,我们可以使用中间件使分片对中/大型项目的用户透明。
以下是我的小项目的快速解决方法(我是唯一的开发人员):
第一步,创建一个拦截器:
public class mysqlInterceptor extends EmptyInterceptor
private String entityName;
@Setter
private int tableId;
protected MySqlInterceptor()
super();
public MySqlInterceptor(String entityName)
this.entityName = entityName;
@Override
public String onPrepareStatement(String sql)
// Here is the trick.
String modifiedSql = sql.replaceAll(entityName, entityName + tableId);
log.debug("", modifiedSql);
return modifiedSql;
第 2 步,启动拦截器:
MySqlInterceptor mySqlInterceptor = new MySqlInterceptor("temp");
mySqlInterceptor.setTableId(tableId);
session = entityManagerFactory.unwrap(SessionFactory.class).withOptions().interceptor(mySqlInterceptor).openSession();
说明:
Hibernate 使用 JDBC 与数据库进行通信。拦截器将在运行时将 sql 中的表名从 an entity's name
(在我的情况下是 temp)更改为 a real table name
(temp1,temp2,...)。
P.S. 使用多线程时要小心。
【讨论】:
以上是关于Spring Boot JPA:将一个实体映射到具有相同列的多个(很多)表的主要内容,如果未能解决你的问题,请参考以下文章
如何将 TIMESTAMP 列映射到 ZonedDateTime JPA 实体属性?
JPA Spring Boot 微服务 - 使用两个多对一映射持久化实体时的无限循环
在 Spring Boot jpa 中将多个外键映射到同一个主键
Spring Boot RESTful API 的层设计及其实体映射