I am migrating a project to Spring Boot 3 and Hibernate 6.5.3.Final and encountered a problem when my application use Instant in a legacy project
I have entity:
@Data
@Entity
@SuperBuilder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
public class TestEnity {
@NonNull
private UUID id;
@NonNull
private Instant createDate;
}
Add record by EntityManager (in my timezone now 12 am) with property spring.jpa.properties.hibernate.type.preferred_instant_jdbc_type=TIMESTAMP:
id | create_date
----------------------------------------------------------------------
3ceca36e-710f-4ea3-223b-1118b0796c7f | 2025-04-10 12:20:30.510548
3ceca36e-710f-4ea3-223b-2228b0796c7f | 2025-04-09 12:20:30.510548
3ceca36e-710f-4ea3-223b-3338b0796c7f | 2025-04-08 12:20:30.510548
And I use querydsl for get records:
SQLQueryFactory sqlQueryFactory = new SQLQueryFactory(GenaratorQsqlUtils.createConfiguration(), dataSource);
BooleanBuilder booleanBuilder = new BooleanBuilder();
booleanBuilder.and(getDateFrom(instantFrom));
booleanBuilder.and(getDateTo(instantTo));
long count = sqlQueryFactory.select()
.from(testE)
.where(booleanBuilder) //createDate >= 2025-04-09T12:19:58Z && createDate <= 2025-04-10T12:29:58Z
.fetchCount();
And I wait I get 2 record 1118b0796c7f and 2228b0796c7f, but hibernate find only 1118b0796c7f and in debug I see:
id | create_date
----------------------------------------------------------------------
3ceca36e-710f-4ea3-223b-1118b0796c7f | 2025-04-10 10:20:30.510548
If I update record 2228b0796c7f column create_date for 2025-04-09 14:20:30.510548 (that is, in the current offset recorded in the database, I added another one +02) than I get 2 records
In hibernate 5 all was OK and I not use spring.jpa.properties.hibernate.type.preferred_instant_jdbc_type=TIMESTAMP, but now without spring.jpa.properties.hibernate.type.preferred_instant_jdbc_type I see in database UTC time and when I write rows
How I can configure Hibernate 6 work for backward compatibility? Why when record write time convert in UTC?
You're hitting one of the critical behavior changes in Hibernate 6 (starting around 6.2+) and Spring Boot 3 when using Instant
in entities. Specifically, it's about how Hibernate interprets and persists time zones when saving Instant
to a database using the TIMESTAMP
vs TIMESTAMP WITH TIME ZONE
types.
Refer this link for release note
You can troubleshoot and resolve the issue by considering the following approach:
In Hibernate 6, the handling of Instant
has changed, which can impact how timestamps are stored and compared—especially when using QueryDSL
. To ensure consistent and predictable behavior (with all persisted data being in UTC), it's recommended to explicitly set the time zone to UTC.
Please try adding the following property to your application.properties
file:
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
This configuration instructs Hibernate to convert all temporal values to UTC both when persisting and retrieving data, aligning behavior with what was observed in earlier versions (e.g., Hibernate 5).
Additionally, you do not need to include the property below:
spring.jpa.properties.hibernate.type.preferred_instant_jdbc_type=TIMESTAMP
Omitting it helps Hibernate default to the appropriate JDBC mapping for Instant
, avoiding unexpected time zone shifts during persistence or queries.