revise new doc section

This commit is contained in:
Gavin King 2024-11-16 21:19:42 +01:00
parent 06961d7dbe
commit 632485f8b1
1 changed files with 26 additions and 11 deletions

View File

@ -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`. 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]. 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. 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. 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`. 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 .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` | `LocalDate` | `DATE` | `DATE` | `DATE` | `DATE` 💀
| `LocalTime` | `TIME` | `TIME` | `TIME` | `LocalTime` | `TIME` | `TIME` | `TIME` | `TIMESTAMP` 💀
| `LocalDateTime` | `TIMSTAMP` | `DATETIME` | `DATETIME2` | `LocalDateTime` | `TIMSTAMP` | `DATETIME` | `DATETIME2` | `TIMESTAMP`
| `OffsetDateTime` | `TIMESTAMP WITH TIME ZONE` | `TIMESTAMP` 💀 | `DATETIMEOFFSET` | `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: By default:
- `Duration` is mapped to a column of type `NUMERIC(21)` holding the length of the duration in nanoseconds, and - `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`. 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] [source,java]
---- ----
// store the Instant as a TIMESTAMP WITH TIME ZONE, instead of as a TIMESTAMP
@JdbcTypeCode(SqlTypes.TIMESTAMP_WITH_TIMEZONE) @JdbcTypeCode(SqlTypes.TIMESTAMP_WITH_TIMEZONE)
Instant instant; 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] [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); 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] [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. 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`. 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]] [[embeddable-objects]]