From 632485f8b185fa67dfb4e7f2bdc55901b3768556 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 16 Nov 2024 21:19:42 +0100 Subject: [PATCH] revise new doc section --- .../main/asciidoc/introduction/Entities.adoc | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/documentation/src/main/asciidoc/introduction/Entities.adoc b/documentation/src/main/asciidoc/introduction/Entities.adoc index 6585e2884f..9e8dd572b8 100644 --- a/documentation/src/main/asciidoc/introduction/Entities.adoc +++ b/documentation/src/main/asciidoc/introduction/Entities.adoc @@ -851,24 +851,25 @@ Dates and times should always be represented using the types defined in `java.ti ==== Never use the legacy types `java.sql.Date`, `java.sql.Time`, `java.sql.Timestamp`, or `java.util.Date`. At our urging, support for these types has even been https://in.relation.to/2024/04/22/stop-using-date/[officially deprecated in JPA 3.2]. -Eventually, we hope to completely remove support for these types. +Eventually, we hope to completely remove support for these types from the JPA spec and from Hibernate. ==== Some of the types in `java.time` map naturally to an ANSI SQL column type. A source of confusion is that some databases still don't follow the ANSI standard naming here. Also, as you're probably aware, the `DATE` type on Oracle is not an ANSI SQL `DATE`. +In fact, Oracle doesn't have `DATE` or `TIME` types--every date or time must be stored as a timestamp. .Type mappings from `java.time` to ANSI SQL |==== -| `java.time` class | ANSI SQL type | MySQL | SQL Server +| `java.time` class | ANSI SQL type | MySQL | SQL Server | Oracle -| `LocalDate` | `DATE` | `DATE` | `DATE` -| `LocalTime` | `TIME` | `TIME` | `TIME` -| `LocalDateTime` | `TIMSTAMP` | `DATETIME` | `DATETIME2` -| `OffsetDateTime` | `TIMESTAMP WITH TIME ZONE` | `TIMESTAMP` 💀 | `DATETIMEOFFSET` +| `LocalDate` | `DATE` | `DATE` | `DATE` | `DATE` 💀 +| `LocalTime` | `TIME` | `TIME` | `TIME` | `TIMESTAMP` 💀 +| `LocalDateTime` | `TIMSTAMP` | `DATETIME` | `DATETIME2` | `TIMESTAMP` +| `OffsetDateTime`, `ZonedDateTime` | `TIMESTAMP WITH TIME ZONE` | `TIMESTAMP` 🙄 | `DATETIMEOFFSET` | `TIMESTAMP WITH TIME ZONE` |==== -On the other hand, there are no perfectly natural mappings for `Instant` and `Duration`. +On the other hand, there are no perfectly natural mappings for `Instant` and `Duration` on must databases. By default: - `Duration` is mapped to a column of type `NUMERIC(21)` holding the length of the duration in nanoseconds, and @@ -876,19 +877,21 @@ By default: Fortunately, these mappings can be modified by specifying the `JdbcType`. -For example, if we wanted to store an `Instant` using `TIMESTAMP WITH TIME ZONE` (`TIMESTAMP` on MySQL) instead of `TIMESTAMP`, then we could annotated the field: +For example, if we wanted to store an `Instant` using `TIMESTAMP WITH TIME ZONE` (`TIMESTAMP` on MySQL) instead of `TIMESTAMP`, then we could annotate the field: [source,java] ---- +// store the Instant as a TIMESTAMP WITH TIME ZONE, instead of as a TIMESTAMP @JdbcTypeCode(SqlTypes.TIMESTAMP_WITH_TIMEZONE) Instant instant; ---- -Alternatively, we could set the property `hibernate.type.preferred_instant_jdbc_type`: +Alternatively, we could set the configuration property `hibernate.type.preferred_instant_jdbc_type`: [source,java] ---- +// store field of type Instant as TIMESTAMP WITH TIME ZONE, instead of as a TIMESTAMP config.setProperty(MappingSettings.PREFERRED_INSTANT_JDBC_TYPE, SqlTypes.TIMESTAMP_WITH_TIMEZONE); ---- @@ -897,10 +900,22 @@ In particular, Hibernate is very careful in how it handles time zones. [WARNING] ==== -Unfortunately, most SQL databases feature embarrassingly poor support for timezones. +Unfortunately, with the notable exception of Oracle, most SQL databases feature embarrassingly poor support for timezones. Even some databases which do supposedly support `TIMESTAMP WITH TIME ZONE` simply covert the datetime to UTC. Here, Hibernate is limited by the capabilities of the databases themselves, and so on many databases, time zone information will not, by default, be preserved for an `OffsetDateTime` or `ZonedDateTime`. -The still-experimental annotation link:{doc-javadoc-url}org/hibernate/annotation/TimeZoneStorage.html[`@TimeZoneStorage`] provides some additional options in case the default behavior falls short. +==== + +[TIP] +==== +The still-experimental annotation link:{doc-javadoc-url}org/hibernate/annotations/TimeZoneStorage.html[`@TimeZoneStorage`] provides some additional options in case the default behavior falls short. +// +// [source,java] +// ---- +// @TimeZoneStorage(COLUMN) +// @TimeZoneColumn(name = "event_offset") +// @Column(name = "event_timestamp") +// private OffsetDateTime eventDateTime; +// ---- ==== [[embeddable-objects]]