【问题标题】:Single-quoting parameter values in Spring JPA/Hibernate Native query (PostgreSQL)Spring JPA/Hibernate Native 查询(PostgreSQL)中的单引号参数值
【发布时间】:2015-12-17 20:16:43
【问题描述】:

我有一个将事件存储在“事件”表中的数据库,该事件的多个读数存储在“读取”表中,外键为事件 id。事件本身有一个以 UTC 格式存储的时间戳(Timestamp with Time Zone)。但是,我有多个时区的用户,并且想在用户的时区中总结给定日期的读数。

我能够使用本机查询成功查询以检索给定日期 (UTC) 的最大、最小和平均读数:

@Query(nativeQuery=true, value="SELECT source, to_char(timestamp, 'yyyy-MM-dd') as \"date\", min(decimalreading), max(decimalreading), avg(decimalreading) " +
                "FROM reading, event " +
                "WHERE reading.event = event.id and source = ?1 "+
                "and timestamp between ?2 and ?3 "+
                "GROUP BY event.source, to_char(timestamp, 'yyyy-MM-dd') " +
                "ORDER BY source, to_char(timestamp, 'yyyy-MM-dd')")
List<Object[]> minMax(long source, Calendar from, Calendar to);

Postgres 很好地支持“时区时间戳”语法,所以我尝试了:

@Query(nativeQuery=true, value="SELECT source, to_char(timestamp at time zone ?4, 'yyyy-MM-dd') as \"date\", min(decimalreading), max(decimalreading), avg(decimalreading) " +
                "FROM reading, event " +
                "WHERE reading.event = event.id and source = ?1 " +
                "and timestamp at time zone ?4 between ?2 and ?3 "+
                "GROUP BY event.source, to_char(timestamp at time zone ?4, 'yyyy-MM-dd') " +
                "ORDER BY source, to_char(timestamp at time zone ?4, 'yyyy-MM-dd')")
List<Object[]> minMax(long source, Calendar from, Calendar to, String timezone);

通过这种形式的查询,我得到了

event.timestamp 必须出现在 GROUP_BY 子句中或用于 聚合函数

调试 Hibernate SQL 将查询显示为:

DEBUG SQL:109 - SELECT source, to_char(timestamp at time zone ?, 'yyyy-MM-dd') 作为“日期”,min(decimalreading),max(decimalreading), avg(decimalreading) FROM reading, event WHERE reading.event = event.id 和时区的时间戳?之间 ?和 ? GROUP BY event.source, to_char(timestamp at time zone ?, 'yyyy-MM-dd') ORDER BY source, to_char(timestamp at time zone ?, 'yyyy-MM-dd')

如果我将 ?4 括在单引号 ('?4') 中,我会得到 ​​p>

java.lang.IllegalArgumentException:具有该位置的参数 [4] 不存在

很明显,效果并没有更好,而且它根本看不到查询中的参数。

我也尝试过 ''?4'' 和 \'?4\',但没有更好的成功。

如果我将 ?4 位置参数替换为硬编码值“cst5cdt”,则查询将成功执行。它还可以通过 pgadmin 中的 sql 提示很好地执行。

我怀疑这是准备好的语句或处理位置参数的方式的问题。

是否有一种语法可以让我在作为参数传入的时区中聚合当天的数据?

【问题讨论】:

  • 是我遗漏了什么,还是您的方法只接受 4 个参数,而您指的是第五个参数?
  • 是的,这是因为我编辑了一些与问题无关的信息,并且做得很糟糕......编辑了问题,感谢您指出!

标签: java hibernate postgresql jpa spring-data


【解决方案1】:

我找到了一种方法来做到这一点,虽然它有点复杂。选择时区作为子查询可以将其正确插入到主查询中:

@Query(nativeQuery=true, value="SELECT source, to_char(timestamp at time zone local.tz, 'yyyy-MM-dd') as \"date\", min(decimalreading), max(decimalreading), avg(decimalreading) " +
                "FROM reading, event, (select ?4 as tz) as local " +
                "WHERE reading.event = event.id "+
                "and source = ?1 " +
                "and timestamp at time zone local.tz between ?2 and ?3 "+
                "GROUP BY event.source, to_char(timestamp at time zone local.tz, 'yyyy-MM-dd') " +
                "ORDER BY well, to_char(timestamp at time zone local.tz, 'yyyy-MM-dd')")
List<Object[]> minMax(long source, Calendar from, Calendar to, String timezone);

有兴趣了解是否有其他方法可能不那么……粗鲁。

【讨论】:

    猜你喜欢
    • 2022-01-07
    • 2018-03-17
    • 1970-01-01
    • 2016-06-26
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2020-01-08
    相关资源
    最近更新 更多