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 的层设计及其实体映射

Spring Boot JPA @JoinTable 与现有映射表忽略 @GeneratedValue

Spring boot JPA - 延迟加载不适用于一对一映射