JPA 2.2中TemporalType.TIMESTAMP设置查询参数时间变为00:00:00问题
JPA/Hibernate迁移后HQL查询中日期时间部分被截断的问题分析与解决
从JPA 2/Hibernate 4/Java 7迁移到JPA 2.2/Hibernate 5.3.24/Java 11后出现的日期时间截断问题,并非JPA规范变更导致,核心原因是Hibernate 5.x对java.util.Date的处理逻辑调整,以及Java 11环境下旧日期类型的交互变化。
问题根源
Hibernate 4.x时代会自动根据实体字段的@Temporal(TemporalType.TIMESTAMP)推断参数类型,但Hibernate 5.x在处理java.util.Date参数时,即使显式指定TemporalType.TIMESTAMP,也可能因为Java 11中java.util.Date与java.sql.Date的类型转换逻辑变化,被误绑定为DATE类型,从而截断时间部分。
解决办法
1. 显式转换为java.sql.Timestamp传入参数
在设置参数时,将java.util.Date转换为java.sql.Timestamp,确保Hibernate识别为完整的时间戳类型:
q.setParameter("dateStarted", new java.sql.Timestamp(session.getDateStarted().getTime()), TemporalType.TIMESTAMP);
2. 迁移到Java 8+时间API(推荐方案)
Java 8引入的LocalDateTime等时间类是线程安全的,且Hibernate 5.3对其有原生支持,彻底避免旧日期类型的兼容性问题:
- 修改实体字段定义:
@Column(name = "date_started", nullable = false, length = 29) public LocalDateTime getDateStarted() { return this.dateStarted; }
- 查询参数设置无需指定
TemporalType,Hibernate会自动适配:
q.setParameter("dateStarted", session.getDateStarted());
3. 检查Hibernate配置
确认是否存在强制日期类型的配置项,比如:
# 确保该配置未被设置为DATE hibernate.type.preferred_date_time_jdbc_type=TIMESTAMP
验证方法
开启Hibernate的参数绑定日志,查看实际绑定的类型:
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
日志中会显示参数绑定的JDBC类型,确认是否为TIMESTAMP而非DATE。
内容的提问来源于stack exchange,提问作者DaveB
相关产品推荐
相关产品推荐

