Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring JPA Hibernate CET timezone for AuditingEntityListener

I'm not succeeding at setting a CET timezone for my JPA application, which is using the AuditingEntityListener to augment creation/lastmodified dates.

Things I tried already:

In my application.properties (both combinations):

spring.jpa.properties.hibernate.jdbc.time_zone=UTC+1
spring.jpa.properties.hibernate.jdbc.time_zone=CET

Added timezone to my JDBC connection (both combinations)

spring.datasource.url=jdbc:mysql://host:3306/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC+1
spring.datasource.url=jdbc:mysql://host:3306/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=CET

Added a postconstruct (application level)

@PostConstruct
void started() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC+1"));
}

And also tried setting the timezone at database level using:

SET time_zone='+01:00';

No succeed whatsoever, Am I missing something?

Using the @createdDate as follows:

EDIT

@Data
@Builder
@Entity
@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor
@AllArgsConstructor
public class OrderHistoryRecord {
    @Id
    @GeneratedValue
    @JsonIgnore
    private Long id;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY, targetEntity = Order.class)
    @JoinColumn(name = "order_id", updatable = false)
    @JsonIgnore
    private Order order;

    @CreatedDate
    private Date date;

    @Enumerated(EnumType.STRING)
    private PaymentStatus paymentStatus;

    @Enumerated(EnumType.STRING)
    private ShipmentStatus shipmentStatus;

    @Enumerated(EnumType.STRING)
    private OrderHistoryRecordType type;
}
like image 622
LaurensVijnck Avatar asked Mar 19 '19 21:03

LaurensVijnck


1 Answers

I had the same issue and solved it by configuring a custom DateTimeProvider which uses UTC instead of the system timezone, see code below.

The mentioned solution to set the values manually feels not right to me because it mixes up the Spring JPA extension and the EntityListener support, why would you use JPA Auditing from Spring at all?

Solution for Spring Boot 1

@Configuration
@EnableJpaAuditing(dateTimeProviderRef = "utcDateTimeProvider")
public class JpaConfig {
    @Bean
    public DateTimeProvider utcDateTimeProvider() {
        return () -> new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    }
}

Why Gregoriancalendar? Spring will convert the object of type GregorianCalendar to a LocalDateTime by using the converters Jsr310Converters.

Solution for Spring Boot 2

@Configuration
@EnableJpaAuditing(dateTimeProviderRef = "utcDateTimeProvider")
public class JpaConfig {
    @Bean
    public DateTimeProvider utcDateTimeProvider() {
        return () -> Optional.of(LocalDateTime.now(ZoneOffset.UTC));
    }
}

I hope it helps :)

like image 114
judomu Avatar answered Oct 07 '22 05:10

judomu