You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL与Hibernate执行相同date_part查询返回结果不一致

问题根因

你遇到的是JDBC会话时区和psql会话时区不一致导致的计算偏差,-180分钟恰好对应3小时的时区差,和你怀疑的时区问题方向一致,只是排查点有遗漏:

  • psql执行查询时用的是本地客户端/数据库默认的会话时区,计算逻辑符合预期
  • Hibernate通过JDBC连接数据库时,会话时区未对齐,导致current_timestamp取到的是JDBC会话对应时区的时间,和created字段存储的时区基准不一致,新作业的created时间按错误时区换算后甚至会晚于当前查询时间,最终得到负值。
  • 换用extract方法无效的原因是:两种函数都是基于当前会话的时区做时间拆分,底层时间基准已经错误,上层函数调整不会改变结果。

验证方法

在你的原生查询中临时新增时区查询字段,确认两者差值:

@Query(value = "SELECT current_setting('timezone') as session_timezone, bind_name, type_name, max((24 * 60 * date_part('day', current_timestamp - created)) + (60 * date_part('hour', current_timestamp - created)) + (date_part('minute', current_timestamp - created))) FROM job WHERE state IN ('INITIAL', 'SUBMITTED') AND bind_name IS NOT NULL AND  type_name IS NOT NULL GROUP BY session_timezone, bind_name, type_name", nativeQuery = true)

分别打印Hibernate查询返回的session_timezone和psql执行select current_setting('timezone');的结果,两者必然不同。

解决方案

任选一种即可:

  • 强制JDBC连接时区:在数据库连接字符串中增加时区参数,和数据库全局时区对齐,示例(以东八区为例):
    jdbc:postgresql://xxx:5432/db_name?serverTimezone=Asia/Shanghai&useTimezone=true
    
  • 查询时固定时区基准:修改SQL语句,统一使用标准时区计算,避免会话时区影响:
    -- 示例统一用东八区计算
    max((24 * 60 * date_part('day', now() AT TIME ZONE 'Asia/Shanghai' - created AT TIME ZONE 'Asia/Shanghai')) + (60 * date_part('hour', now() AT TIME ZONE 'Asia/Shanghai' - created AT TIME ZONE 'Asia/Shanghai')) + (date_part('minute', now() AT TIME ZONE 'Asia/Shanghai' - created AT TIME ZONE 'Asia/Shanghai')))
    
  • 全局对齐JVM时区:Spring Boot启动参数增加JVM时区配置,和数据库时区一致:
    java -Duser.timezone=Asia/Shanghai -jar your_app.jar
    

内容的提问来源于stack exchange,提问作者Frederick Haug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:15:03