David Rochin
David Rochin

Reputation: 377

Why does Hibernate map LocalDateTime to timestamp (MySQL) and how can I prevent it from doing so?

  1. I think it is known that the timestamp column type in MySQL is meant to store "moments" in time.

  2. According to LocalDateTime official docs, this class is:

A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30. LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second

and is commonly used to store dates with time, NOT "moments" in time (it doesn't store using UTC as reference like other "moment" data types like Instant).

Then why does Hibernate map LocalDateTime fields to timestamp fields in the database? As I understand it, they are meant for different things!

It's causing me problems where I want to store raw LocalDateTime values in my database, but Hibernate ruins this by internally converting all my database datetimes to "moments" first (specifically to java.sql.Timestamp)

Is this a bug? A design flaw? Or am I in the wrong here?

By the way, I have tried setting up my entities like this

public class MyEntity implements Serializable {

    @Id
    private Long id;

    @Column(name = "my_date_time_field", columnDefinition = "DATETIME")
    private LocalDateTime myDateTimeField = LocalDateTime.now();

and Hibernate still does some awkard conversion when fetching from the DB because it thinks I'm fetching a "moment" instead of a "local date/time" value (still uses TimestampTypeDescriptor internally, where it converts to Timestamp before doing anything else).

PD: I know it's standard to handle all dates/times in UTC. Because of client requirements, I cannot do this. They only want to see local dates and times in the DB, and never see them converted, even if they are on a different timezone. They have explicity told me they don't care about the concept of "moments" because their business does not function AT ALL like that (After weeks of explaining and arguing about this, I'm pretty sure they know what consequences that brings).

Upvotes: 1

Views: 2153

Answers (1)

coladict
coladict

Reputation: 5095

This is done because the JDBC drivers can only be expected to support java.sql.Date, java.sql.Time and java.sql.Timestamp types, and there is no standard mechanism for checking what types the driver supports for using setObject for the parameters. Even if the MySQL driver supports it, there is no way of knowing if any outdated middleware abstraction layer won't try to validate that parameter and reject it.

Therefore, to ensure maximum compatibility the java.time.* types are converted to the java.sql.* types, and the JDBC driver only gives you java.time.* types that you have to make some assumptions on how they are used internally.

This is not a design-flaw in Hibernate, it is their approach to an undefined behavior in the available standards. And even if mechanisms to address this are introduced in the JDBC standards, it would still be years before support propagates enough on all levels that they can make use of it.

Upvotes: 3

Related Questions