javaspringhibernate

Changing write and read Instant after update from hibernate 5 to 6


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?


Solution

  • 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.