You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation/src/main/asciidoc/introduction/Entities.adoc
+95-4Lines changed: 95 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -656,10 +656,20 @@ But in the country I was born, `SUNDAY` is the _first_ day of the week!
656
656
So we prefer `@Enumerated(STRING)` for most `enum` attributes.
657
657
====
658
658
659
-
An interesting special case is PostgreSQL.
660
-
Postgres supports _named_ `ENUM` types, which must be declared using a DDL `CREATE TYPE` statement.
661
-
Sadly, these `ENUM` types aren't well-integrated with the language nor well-supported by the Postgres JDBC driver, so Hibernate doesn't use them by default.
662
-
But if you would like to use a named enumerated type on Postgres, just annotate your `enum` attribute like this:
659
+
An interesting special case arises on PostgreSQL and Oracle.
660
+
661
+
[[named-enums]]
662
+
.Named enumerated types
663
+
****
664
+
Some databases support _named_ `ENUM` types, which must be declared using in DDL using:
665
+
666
+
- `CREATE TYPE ... AS ENUM` on PostgreSQL, or
667
+
- `CREATE DOMAIN ... AS ENUM` on Oracle.
668
+
669
+
These look like a perfect match for Java ``enum``s, which also have names!
670
+
671
+
Sadly, these `ENUM` types aren't well-integrated with the SQL language, nor well-supported by the JDBC drivers, so Hibernate doesn't use them by default.
672
+
But if you would like to use a named enumerated type on Postgres or Oracle, just annotate your `enum` attribute like this:
663
673
664
674
[source,java]
665
675
----
@@ -668,6 +678,9 @@ But if you would like to use a named enumerated type on Postgres, just annotate
668
678
Status status;
669
679
----
670
680
681
+
Alternatively, you may enable the configuration property link:{doc-javadoc-url}org/hibernate/cfg/MappingSettings.html#PREFER_NATIVE_ENUM_TYPES[`hibernate.type.prefer_native_enum_types`].
682
+
****
683
+
671
684
The limited set of pre-defined basic attribute types can be stretched a bit further by supplying a _converter_.
672
685
673
686
[[converters]]
@@ -740,6 +753,7 @@ Hibernate considers a "basic type" to be formed by the marriage of two objects:
740
753
741
754
When mapping a basic attribute, we may explicitly specify a `JavaType`, a `JdbcType`, or both.
742
755
756
+
[[java-type]]
743
757
[discrete]
744
758
==== JavaType
745
759
@@ -771,6 +785,7 @@ BitSet bitSet;
771
785
772
786
Alternatively, the `@JavaTypeRegistration` annotation may be used to register `BitSetJavaType` as the default `JavaType` for `BitSet`.
773
787
788
+
[[jdbc-type]]
774
789
[discrete]
775
790
==== JdbcType
776
791
@@ -827,6 +842,82 @@ long currentTimeMillis;
827
842
828
843
Let's abandon our analogy right here, before we start calling this basic type a "throuple".
829
844
845
+
[[datetime-types]]
846
+
=== Date and time types, and time zones
847
+
848
+
Dates and times should always be represented using the types defined in `java.time`.
849
+
850
+
[WARNING]
851
+
====
852
+
Never use the legacy types `java.sql.Date`, `java.sql.Time`, `java.sql.Timestamp`, or `java.util.Date`.
853
+
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].
854
+
Eventually, we hope to completely remove support for these types from the JPA spec and from Hibernate.
855
+
====
856
+
857
+
Some of the types in `java.time` map naturally to an ANSI SQL column type.
858
+
A source of confusion is that some databases still don't follow the ANSI standard naming here.
859
+
Also, as you're probably aware, the `DATE` type on Oracle is not an ANSI SQL `DATE`.
860
+
In fact, Oracle doesn't have `DATE` or `TIME` types--every date or time must be stored as a timestamp.
861
+
862
+
.Type mappings from `java.time` to ANSI SQL
863
+
|====
864
+
| `java.time` class | ANSI SQL type | MySQL | SQL Server | Oracle
| `OffsetDateTime`, `ZonedDateTime` | `TIMESTAMP WITH TIME ZONE` | `TIMESTAMP` 🙄 | `DATETIMEOFFSET` | `TIMESTAMP WITH TIME ZONE`
870
+
|====
871
+
872
+
On the other hand, there are no perfectly natural mappings for `Instant` and `Duration` on must databases.
873
+
By default:
874
+
875
+
- `Duration` is mapped to a column of type `NUMERIC(21)` holding the length of the duration in nanoseconds, and
876
+
- `Instant` is mapped to a column of type `TIMESTAMP` (`DATETIME` on MySQL).
877
+
878
+
Fortunately, these mappings can be modified by specifying the `JdbcType`.
879
+
880
+
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:
881
+
882
+
[source,java]
883
+
----
884
+
// store the Instant as a TIMESTAMP WITH TIME ZONE, instead of as a TIMESTAMP
885
+
@JdbcTypeCode(SqlTypes.TIMESTAMP_WITH_TIMEZONE)
886
+
Instant instant;
887
+
----
888
+
889
+
Alternatively, we could set the configuration property `hibernate.type.preferred_instant_jdbc_type`:
890
+
891
+
892
+
[source,java]
893
+
----
894
+
// store field of type Instant as TIMESTAMP WITH TIME ZONE, instead of as a TIMESTAMP
We have worked very hard to make sure that Java date and time types work with consistent and correct semantics across all databases supported by Hibernate.
899
+
In particular, Hibernate is very careful in how it handles time zones.
900
+
901
+
[WARNING]
902
+
====
903
+
Unfortunately, with the notable exception of Oracle, most SQL databases feature embarrassingly poor support for timezones.
904
+
Even some databases which do supposedly support `TIMESTAMP WITH TIME ZONE` simply covert the datetime to UTC.
905
+
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`.
906
+
====
907
+
908
+
[TIP]
909
+
====
910
+
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.
Copy file name to clipboardExpand all lines: documentation/src/main/asciidoc/introduction/Mapping.adoc
+21-16Lines changed: 21 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -734,6 +734,7 @@ Of course, the behavior here depends very much on the JDBC driver, and so we rea
734
734
735
735
There's a couple of alternative ways to represent an embeddable type on the database side.
736
736
737
+
[[embeddable-udt]]
737
738
[discrete]
738
739
==== Embeddables as UDTs
739
740
@@ -818,32 +819,34 @@ Here we summarize the ones we've just seen in the second half of this chapter, a
818
819
|===
819
820
| Annotation | Interpretation
820
821
821
-
| `@Enumerated`, `@EnumeratedValue` | Specify how an `enum` type should be persisted
822
-
| `@Nationalized` | Use a nationalized character type: `NCHAR`, `NVARCHAR`, or `NCLOB`
823
-
| `@Lob` 💀 | Use JDBC LOB APIs to read and write the annotated attribute
824
-
| `@Array` | Map a collection to a SQL `ARRAY` type of the specified length
825
-
| `@Struct` | Map an embeddable to a SQL UDT with the given name
826
-
| `@TimeZoneStorage` | Specify how the time zone information should be persisted
827
-
| `@JdbcType` or `@JdbcTypeCode` | Use an implementation of `JdbcType` to map an arbitrary SQL type
822
+
| `@Enumerated`, `@EnumeratedValue` | Specify how an <<enums,`enum` type should be persisted>>
823
+
| `@Nationalized` | Use a <<nationalized-chars,nationalized character type>>: `NCHAR`, `NVARCHAR`, or `NCLOB`
824
+
| `@Lob` 💀 | Use <<lobs,JDBC LOB APIs>> to read and write the annotated attribute
825
+
| `@Array` | Map a collection to a <<arrays,SQL `ARRAY` type>> of the specified length
826
+
| `@Struct` | Map an <<embeddable-udt,embeddable to a SQL UDT>> with the given name
827
+
| `@TimeZoneStorage` | Specify how the link:{doc-javadoc-url}org/hibernate/annotations/TimeZoneStorageType.html[time zone information should be persisted]
828
+
| `@JdbcType` or `@JdbcTypeCode` | Use an implementation of <<jdbc-type,`JdbcType`>> to map an arbitrary SQL type
828
829
| `@Collate` | Specify a collation for a column
829
830
|===
830
831
831
-
In addition, there are some configuration properties which have a _global_ affect on how basic types map to SQL column types:
832
+
In addition, there are link:{doc-javadoc-url}org/hibernate/cfg/MappingSettings.html[some configuration properties] which have a _global_ effect on how basic types map to SQL column types:
832
833
833
834
.Type mapping settings
834
835
[%autowidth.stretch]
835
836
|===
836
837
| Configuration property name | Purpose
837
838
838
-
| `hibernate.use_nationalized_character_data` | Enable use of nationalized character types by default
839
-
| `hibernate.type.preferred_boolean_jdbc_type` | Specify the default SQL column type for mapping `boolean`
840
-
| `hibernate.type.preferred_uuid_jdbc_type` | Specify the default SQL column type for mapping `UUID`
841
-
| `hibernate.type.preferred_duration_jdbc_type` | Specify the default SQL column type for mapping `Duration`
842
-
| `hibernate.type.preferred_instant_jdbc_type` | Specify the default SQL column type for mapping `Instant`
843
-
| `hibernate.timezone.default_storage` | Specify the default strategy for storing time zone information
844
-
| `` |
839
+
| `hibernate.use_nationalized_character_data` | Enable use of <<nationalized-chars,nationalized character types>> by default
840
+
| `hibernate.type.preferred_boolean_jdbc_type` | Specify the default SQL column type for storing a `boolean`
841
+
| `hibernate.type.preferred_uuid_jdbc_type` | Specify the default SQL column type for storing a `UUID`
842
+
| `hibernate.type.preferred_duration_jdbc_type` | Specify the default SQL column type for storing a `Duration`
843
+
| `hibernate.type.preferred_instant_jdbc_type` | Specify the default SQL column type for storing an `Instant`
844
+
| `hibernate.timezone.default_storage` | Specify the default strategy for link:{doc-javadoc-url}org/hibernate/annotations/TimeZoneStorageType.html[storing time zone information]
845
+
| `hibernate.type.prefer_native_enum_types` | Use <<named-enums,named enum types>> on PostgreSQL and Oracle
845
846
|===
846
847
848
+
Earlier, we saw how to use these settings to control the default mappings for <<datetime-types,`Instant` and `Duration`>>.
849
+
847
850
[TIP]
848
851
====
849
852
These are _global_ settings and thus quite clumsy.
@@ -863,7 +866,7 @@ Thus, the attribute is a sort of "derived" value.
863
866
|===
864
867
| Annotation | Purpose
865
868
866
-
| `@Formula` | Map an attribute to a SQL formula
869
+
| link:{doc-javadoc-url}org/hibernate/annotations/Formula.html[`@Formula`] | Map an attribute to a SQL formula
867
870
| `@JoinFormula` | Map an association to a SQL formula
868
871
| `@DiscriminatorFormula` | Use a SQL formula as the discriminator in <<mapping-inheritance,single table inheritance>>.
869
872
|===
@@ -887,6 +890,8 @@ class Order {
887
890
}
888
891
----
889
892
893
+
The formula is evaluated every time the entity is read from the database.
0 commit comments