JPQL / Hibernate 查询的动态表名

Posted

技术标签:

【中文标题】JPQL / Hibernate 查询的动态表名【英文标题】:Dyamic table name for JPQL / Hibernate query 【发布时间】:2020-01-03 06:32:25 【问题描述】:

我有一个数据库,其中包含已经(并将继续)使用命名策略创建的数千个表 - 每个日历日一个表:

data_2010_01_01 data_2010_01_02 ... data_2020_01_01

所有表格都包含来自同一系统且形状相同的传感器数据。所以单个实体(我们称之为 SensorRecord)绝对会映射到所有表。

我曾想象过这样的事情会奏效:

@Query(nativeQuery = true, value = "SELECT * FROM \"?1\"")
Collection<SensorRecord> findSensorDataForDate(String tableName);

但事实并非如此,围绕该主题阅读似乎表明我走错了路。大多数关于动态命名的帖子似乎都明确指出每个表需要一个实体,但生成数千个重复实体似乎也是错误的。

我如何使用 JPA (JPQL?) 来处理表名遵循命名约定并且可以作为查询的一部分进行更改的数据?

【问题讨论】:

这能回答你的问题吗? How to replace table name with value from parameter while using Spring Data JPA nativeQuery 部分。一个答案说“你不能”,另一个答案显示了一个实体管理器代码片段,没有说明为什么这是首选解决方案的上下文。下面亚历克斯的回答是一个相当完整和有用的回答。 【参考方案1】:

参数只允许在 where 子句中。 您可以创建自定义存储库方法返回SensorRecord dto 的集合。无需映射这么多实体。您应该得到 List&lt;Object []&gt; 作为查询结果并手动创建 dto 对象。

    @Autowired 
    EntityManager entityManager;    

    public List<SensorRecord> findSensorDataForDate(LocalDate date) 
           DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd");
           String tableName = "data_" + date.format(formatter);

           Query query = entityManager.createNativeQuery(
                             "select t.first_column, t.second_column from " + tableName + " t");

           List<Object[]> queryResults = query.getResultList();

           List<SensorRecord> sensorRecords = new ArrayList<>();
           for (Object[] row : queryResults) 
               SensorRecord record = new SensorRecord();
               record.setFirstParameter((Integer) row[0]);
               record.setSecondParameter((String) row[1]);

               sensorRecords.add(record);
           

           return sensorRecords;
   

【讨论】:

感谢工作示例。这很有帮助。似乎没有办法将表名作为 JPQL 参数,所以这就是我需要的。【参考方案2】:

会不会只是语法错误?

这对我有用:

    @Query(value = "select * from job where job.locked = 1 and job.user = ?1", nativeQuery = true)
    public List<JobDAO> getJobsForUser(@Param("user") String user);

【讨论】:

这个例子有一个固定的表名“job”。我需要能够更改表名。因此,在您的示例中: select * from job_123 或 select * from job_456 ...

以上是关于JPQL / Hibernate 查询的动态表名的主要内容,如果未能解决你的问题,请参考以下文章

Spring JPA 和 Hibernate 的 JPQL 查询错误

如何使用 Hibernate 5 正确创建 JPQL 查询(不推荐使用查询类型)

JPQL 到 SQL 使用 Hibernate 更新查询交叉连接问题

与 SQL 相比,Hibernate JPQL 查询非常慢

无法在 FROM 子句中使用子查询编写 JPQL 查询 - Spring Data Jpa - Hibernate

无法在 FROM 子句中使用子查询编写 JPQL 查询 - Spring Data Jpa - Hibernate