diff --git a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
index 255bc4c3f3..6b56eb2c9f 100644
--- a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
+++ b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
@@ -295,6 +295,20 @@ Assuming `hibernate.globally_quoted_identifiers` is `true`, this allows the glob
`*hibernate.auto_quote_keyword*` (e.g. `true` or `false` (default value))::
Specifies whether to automatically quote any names that are deemed keywords.
+==== Time zone storage
+`*hibernate.timezone.default_storage*` (e.g. `COLUMN`, `NATIVE`, `AUTO` or `NORMALIZE` (default value))::
+Global setting for configuring the default storage for the time zone information for time zone based types.
++
+`NORMALIZE`::: Does not store the time zone, and instead normalizes timestamps to UTC
+`COLUMN`::: Stores the time zone in a separate column; works in conjunction with `@TimeZoneColumn`
+`NATIVE`::: Stores the time zone by using the `with time zone` type. Error if `Dialect#getTimeZoneSupport()` is not `NATIVE`
+`AUTO`::: Stores the time zone either with `NATIVE` if `Dialect#getTimeZoneSupport()` is `NATIVE`, otherwise uses the `COLUMN` strategy.
++
+The default value is given by the {@link org.hibernate.annotations.TimeZoneStorageType#NORMALIZE},
+meaning that time zone information is not stored by default, but timestamps are normalized instead.
++
+See the discussion https://github.com/hibernate/hibernate-orm/discussions/4201[on GitHub] for additional background info.
+
==== Discriminator options
`*hibernate.discriminator.implicit_for_joined*` (e.g. `true` or `false` (default value))::
The legacy behavior of Hibernate is to not use discriminators for joined inheritance (Hibernate does not need the discriminator).
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigDecimalMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigDecimalMappingTests.java
index 6671adbe5b..29334a6ec4 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigDecimalMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigDecimalMappingTests.java
@@ -16,6 +16,7 @@ import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -41,6 +42,8 @@ public class BigDecimalMappingTests {
// first, verify the type selections...
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityOfBigDecimals.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
{
final BasicAttributeMapping attribute = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "wrapper" );
@@ -48,7 +51,7 @@ public class BigDecimalMappingTests {
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( BigDecimal.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), is( Types.NUMERIC ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.NUMERIC ) ) );
}
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigIntegerMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigIntegerMappingTests.java
index 65ac54aa64..1742a4c8bb 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigIntegerMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/BigIntegerMappingTests.java
@@ -16,6 +16,7 @@ import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -41,6 +42,8 @@ public class BigIntegerMappingTests {
// first, verify the type selections...
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityOfBigIntegers.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
{
final BasicAttributeMapping attribute = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "wrapper" );
@@ -48,7 +51,7 @@ public class BigIntegerMappingTests {
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( BigInteger.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), is( Types.NUMERIC ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.NUMERIC ) ) );
}
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/ByteMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/ByteMappingTests.java
index 6b4ca3a28e..d6c1b12ed7 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/ByteMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/ByteMappingTests.java
@@ -16,6 +16,7 @@ import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -43,6 +44,8 @@ public class ByteMappingTests {
// first, verify the type selections...
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityOfBytes.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
{
final BasicAttributeMapping attribute = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "wrapper" );
@@ -50,7 +53,7 @@ public class ByteMappingTests {
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), is( Types.TINYINT ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.TINYINT ) ) );
}
{
@@ -59,7 +62,7 @@ public class ByteMappingTests {
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), is( Types.TINYINT ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.TINYINT ) ) );
}
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/CharacterArrayNationalizedMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/CharacterArrayNationalizedMappingTests.java
index 20c95896a5..f30de2125c 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/CharacterArrayNationalizedMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/CharacterArrayNationalizedMappingTests.java
@@ -19,6 +19,7 @@ import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@@ -29,6 +30,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
/**
* @see CharacterArrayMappingTests
@@ -43,6 +45,8 @@ public class CharacterArrayNationalizedMappingTests {
public void verifyMappings(SessionFactoryScope scope) {
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityWithCharArrays.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
final NationalizationSupport nationalizationSupport = dialect.getNationalizationSupport();
@@ -50,26 +54,26 @@ public class CharacterArrayNationalizedMappingTests {
{
final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "primitiveNVarchar" );
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping();
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getVarcharVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode() ) ) );
}
{
final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "wrapperNVarchar" );
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping();
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getVarcharVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode() ) ) );
}
{
final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "primitiveNClob" );
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping();
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getClobVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode() ) ) );
}
{
final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "wrapperNClob" );
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping();
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getClobVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode() ) ) );
}
}
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/DurationMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/DurationMappingTests.java
index 7383aed50a..9e7b652d09 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/DurationMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/DurationMappingTests.java
@@ -17,6 +17,7 @@ import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -25,6 +26,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
/**
* @author Steve Ebersole
@@ -37,11 +39,13 @@ public class DurationMappingTests {
public void verifyMappings(SessionFactoryScope scope) {
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityWithDuration.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
final BasicAttributeMapping duration = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "duration" );
final JdbcMapping jdbcMapping = duration.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Duration.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( Types.NUMERIC ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.NUMERIC ) ) );
scope.inTransaction(
(session) -> {
diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/StringNationalizedMappingTests.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/StringNationalizedMappingTests.java
index 1065ce554e..eb208ffcbe 100644
--- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/StringNationalizedMappingTests.java
+++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/StringNationalizedMappingTests.java
@@ -6,6 +6,8 @@
*/
package org.hibernate.userguide.mapping.basic;
+import java.sql.Types;
+
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
@@ -18,6 +20,7 @@ import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -27,6 +30,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
/**
* Tests for mapping `double` values
@@ -42,6 +46,8 @@ public class StringNationalizedMappingTests {
// first, verify the type selections...
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( EntityOfStrings.class );
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = domainModel.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
final NationalizationSupport nationalizationSupport = dialect.getNationalizationSupport();
@@ -50,14 +56,14 @@ public class StringNationalizedMappingTests {
final BasicAttributeMapping attribute = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "nstring" );
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( String.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getVarcharVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode() ) ) );
}
{
final BasicAttributeMapping attribute = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "nclobString" );
final JdbcMapping jdbcMapping = attribute.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( String.class ) );
- assertThat( jdbcMapping.getJdbcTypeDescriptor().getJdbcTypeCode(), equalTo( nationalizationSupport.getClobVariantCode() ) );
+ assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode() ) ) );
}
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java
index ee9b790d2d..3d33492f1b 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java
@@ -10,6 +10,7 @@ import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.OracleDialect;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.community.dialect.identity.CUBRIDIdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
@@ -372,8 +373,8 @@ public class CUBRIDDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NATIVE;
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
index 9f717403e0..e90f15350d 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java
@@ -10,6 +10,7 @@ import org.hibernate.HibernateException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.BooleanDecoder;
import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.query.NullOrdering;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
@@ -57,11 +58,9 @@ import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
-import org.hibernate.type.spi.TypeConfiguration;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
-import java.sql.Timestamp;
import java.sql.Types;
import java.time.temporal.TemporalAccessor;
import java.util.Arrays;
@@ -170,8 +169,8 @@ public class FirebirdDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return getVersion() >= 400;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return getVersion() >= 400 ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
}
@Override
@@ -315,7 +314,7 @@ public class FirebirdDialect extends Dialect {
@Override
public String currentLocalTime() {
- if ( supportsTimezoneTypes() ) {
+ if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
return "localtime";
}
else {
@@ -325,7 +324,7 @@ public class FirebirdDialect extends Dialect {
@Override
public String currentLocalTimestamp() {
- if ( supportsTimezoneTypes() ) {
+ if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
return "localtimestamp";
}
else {
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
index 5b1fae7e4d..6636c73bb4 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java
@@ -9,6 +9,7 @@ package org.hibernate.community.dialect;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.community.dialect.identity.Ingres10IdentityColumnSupport;
@@ -318,8 +319,8 @@ public class IngresDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NATIVE;
}
@Override
diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java
index 3bb8dea977..d76c621241 100644
--- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java
+++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java
@@ -10,6 +10,7 @@ package org.hibernate.community.dialect;
import org.hibernate.LockOptions;
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.dialect.SybaseDialect;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.community.dialect.identity.SybaseAnywhereIdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler;
@@ -80,8 +81,8 @@ public class SybaseAnywhereDialect extends SybaseDialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NATIVE;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/TimeZoneStorageStrategy.java b/hibernate-core/src/main/java/org/hibernate/TimeZoneStorageStrategy.java
new file mode 100644
index 0000000000..fe5afcf8e4
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/TimeZoneStorageStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate;
+
+/**
+ * Describes the storage strategies understood by Hibernate.
+ *
+ * @author Christian Beikov
+ * @author Steve Ebersole
+ * @author Andrea Boriero
+ */
+@Incubating
+public enum TimeZoneStorageStrategy {
+ /**
+ * Stores the time zone through the "with time zone" types which retain the information.
+ */
+ NATIVE,
+ /**
+ * Stores the time zone in a separate column.
+ */
+ COLUMN,
+ /**
+ * Doesn't store the time zone, but instead normalizes to UTC.
+ */
+ NORMALIZE;
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneColumn.java b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneColumn.java
new file mode 100644
index 0000000000..1785d1389d
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneColumn.java
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.hibernate.Incubating;
+
+import jakarta.persistence.Column;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
+/**
+ * Specifies the column name and type to use for storing the time zone information.
+ * The annotation can be used in conjunction with the TimeZoneStorageType.AUTO
and
+ * TimeZoneStorageType.COLUMN
. The column is simply ignored if TimeZoneStorageType.AUTO
+ * is used and the database supports native time zone storage.
+ *
+ * @author Christian Beikov
+ * @author Steve Ebersole
+ * @author Andrea Boriero
+ * @see TimeZoneStorage
+ * @see TimeZoneStorageType#COLUMN
+ * @see TimeZoneStorageType#AUTO
+ */
+@Incubating
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ FIELD, METHOD })
+public @interface TimeZoneColumn {
+
+ /**
+ * The column for the time zone information.
+ */
+ Column column();
+
+ /**
+ * The storage type for the time zone information.
+ */
+ TimeZoneType type() default TimeZoneType.OFFSET;
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorage.java b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorage.java
new file mode 100644
index 0000000000..085e5bffea
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorage.java
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.hibernate.Incubating;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
+/**
+ * Specifies how the time zone information of a persistent property or field should be persisted.
+ * The TimeZoneStorage
annotation may be used in conjunction with the Basic
annotation, or in
+ * conjunction with the ElementCollection
annotation when the
+ * element collection value is of basic type. If the TimeZoneStorage
annotation is not
+ * used, the TimeZoneStorageType
value is assumed to be NORMALIZED
.
+ *
+ *
+ * Example:
+ *
+ * @Entity public class Person {
+ * public OffsetDateTime getBirthDateTimeNormalized() {...}
+ *
+ * @TimeZoneStorage
+ * @TimeZoneColumn(column = @Column(...))
+ * public OffsetDateTime getBirthDateTimeNativeOrColumn() {...}
+ * ...
+ * }
+ *
+ *
+ * @author Christian Beikov
+ * @author Steve Ebersole
+ * @author Andrea Boriero
+ * @see TimeZoneColumn
+ */
+@Incubating
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ FIELD, METHOD })
+public @interface TimeZoneStorage {
+ /**
+ * The storage strategy for the time zone information.
+ */
+ TimeZoneStorageType value() default TimeZoneStorageType.AUTO;
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorageType.java b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorageType.java
new file mode 100644
index 0000000000..393ca19413
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneStorageType.java
@@ -0,0 +1,38 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate.annotations;
+
+import org.hibernate.Incubating;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * Describes the storage for the time zone information for time zone based types.
+ *
+ * @author Christian Beikov
+ * @author Steve Ebersole
+ * @author Andrea Boriero
+ */
+@Incubating
+public enum TimeZoneStorageType {
+ /**
+ * Stores the time zone by using the "with time zone" type. Error if {@link Dialect#getTimeZoneSupport()} is not {@link org.hibernate.dialect.TimeZoneSupport#NATIVE}.
+ */
+ NATIVE,
+ /**
+ * Does not store the time zone, and instead normalizes timestamps to UTC.
+ */
+ NORMALIZE,
+ /**
+ * Stores the time zone in a separate column; works in conjunction with {@link TimeZoneColumn}.
+ */
+ COLUMN,
+ /**
+ * Stores the time zone either with {@link #NATIVE} if {@link Dialect#getTimeZoneSupport()} is {@link org.hibernate.dialect.TimeZoneSupport#NATIVE}, otherwise uses the {@link #COLUMN} strategy.
+ */
+ AUTO
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneType.java b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneType.java
new file mode 100644
index 0000000000..737cbf3f55
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/TimeZoneType.java
@@ -0,0 +1,30 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate.annotations;
+
+import org.hibernate.Incubating;
+
+/**
+ * The type of storage to use for the time zone information.
+ *
+ * @author Christian Beikov
+ * @author Steve Ebersole
+ * @author Andrea Boriero
+ */
+@Incubating
+public enum TimeZoneType {
+
+ /**
+ * Stores the time zone id as String.
+ */
+ ZONE_ID,
+ /**
+ * Stores the offset seconds of a timestamp as Integer.
+ */
+ OFFSET;
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/internal/NoJdbcTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/annotations/internal/NoJdbcTypeDescriptor.java
index 9ef9a838aa..c795a525ab 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/internal/NoJdbcTypeDescriptor.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/internal/NoJdbcTypeDescriptor.java
@@ -17,11 +17,6 @@ public class NoJdbcTypeDescriptor implements JdbcTypeDescriptor {
throw new UnsupportedOperationException();
}
- @Override
- public boolean canBeRemapped() {
- throw new UnsupportedOperationException();
- }
-
@Override
public ValueBinder getBinder(JavaTypeDescriptor javaTypeDescriptor) {
throw new UnsupportedOperationException();
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
index 93b9ae6972..f3f2671b3e 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
@@ -16,7 +16,9 @@ import jakarta.persistence.SharedCacheMode;
import org.hibernate.HibernateException;
import org.hibernate.MultiTenancyStrategy;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.annotations.TimeZoneStorageType;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.MetadataBuilder;
@@ -58,8 +60,10 @@ import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.MetadataSourceType;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
+import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger;
@@ -533,6 +537,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
implements MetadataBuildingOptions, JpaOrmXmlPersistenceUnitDefaultAware {
private final StandardServiceRegistry serviceRegistry;
private final MappingDefaultsImpl mappingDefaults;
+ private final TimeZoneStorageStrategy defaultTimezoneStorage;
// todo (6.0) : remove bootstrapContext property along with the deprecated methods
private BootstrapContext bootstrapContext;
@@ -565,6 +570,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
this.mappingDefaults = new MappingDefaultsImpl( serviceRegistry );
+ this.defaultTimezoneStorage = resolveTimeZoneStorageStrategy( serviceRegistry, configService );
this.multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() );
this.xmlMappingEnabled = configService.getSetting(
@@ -744,6 +750,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
return mappingDefaults;
}
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
+ return defaultTimezoneStorage;
+ }
+
@Override
public List getBasicTypeRegistrations() {
return basicTypeRegistrations;
@@ -896,4 +907,54 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
this.bootstrapContext = bootstrapContext;
}
}
+
+ private static TimeZoneStorageStrategy resolveTimeZoneStorageStrategy(
+ StandardServiceRegistry serviceRegistry,
+ ConfigurationService configService) {
+ final TimeZoneStorageType configuredTimeZoneStorageType = configService.getSetting(
+ AvailableSettings.TIMEZONE_DEFAULT_STORAGE,
+ TimeZoneStorageType.class,
+ null
+ );
+ final TimeZoneStorageStrategy resolvedTimezoneStorage;
+ // For now, we default to NORMALIZE as that is the Hibernate 5.x behavior
+ if ( configuredTimeZoneStorageType == null ) {
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.NORMALIZE;
+ }
+ else {
+ final TimeZoneSupport timeZoneSupport = serviceRegistry.getService( JdbcServices.class )
+ .getDialect()
+ .getTimeZoneSupport();
+ switch ( configuredTimeZoneStorageType ) {
+ case NATIVE:
+ if ( timeZoneSupport != TimeZoneSupport.NATIVE ) {
+ throw new HibernateException( "The configured time zone storage type NATIVE is not supported with the configured dialect" );
+ }
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.NATIVE;
+ break;
+ case COLUMN:
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.COLUMN;
+ break;
+ case NORMALIZE:
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.NORMALIZE;
+ break;
+ case AUTO:
+ switch ( timeZoneSupport ) {
+ case NATIVE:
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.NATIVE;
+ break;
+ case NORMALIZE:
+ case NONE:
+ resolvedTimezoneStorage = TimeZoneStorageStrategy.COLUMN;
+ break;
+ default:
+ throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport );
+ }
+ break;
+ default:
+ throw new HibernateException( "Unsupported time zone storage type: " + configuredTimeZoneStorageType );
+ }
+ }
+ return resolvedTimezoneStorage;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
index 747a01906c..e0a40fce03 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java
@@ -27,6 +27,7 @@ import org.hibernate.Interceptor;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.SessionEventListener;
import org.hibernate.SessionFactoryObserver;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.SchemaAutoTooling;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.boot.registry.StandardServiceRegistry;
@@ -219,6 +220,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private boolean conventionalJavaConstants;
private final boolean omitJoinOfSuperclassTablesEnabled;
private final int preferredSqlTypeCodeForBoolean;
+ private final TimeZoneStorageStrategy defaultTimeZoneStorageStrategy;
// Caching
private boolean secondLevelCacheEnabled;
@@ -422,6 +424,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
CONVENTIONAL_JAVA_CONSTANTS, BOOLEAN, true );
this.omitJoinOfSuperclassTablesEnabled = cfgService.getSetting( OMIT_JOIN_OF_SUPERCLASS_TABLES, BOOLEAN, true );
this.preferredSqlTypeCodeForBoolean = ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( serviceRegistry );
+ this.defaultTimeZoneStorageStrategy = context.getMetadataBuildingOptions().getDefaultTimeZoneStorage();
final RegionFactory regionFactory = serviceRegistry.getService( RegionFactory.class );
if ( !NoCachingRegionFactory.class.isInstance( regionFactory ) ) {
@@ -1182,6 +1185,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
public int getPreferredSqlTypeCodeForBoolean() {
return preferredSqlTypeCodeForBoolean;
}
+
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return defaultTimeZoneStorageStrategy;
+ }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// In-flight mutation access
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/VersionResolution.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/VersionResolution.java
index 9bcd979b19..d6eb03f402 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/VersionResolution.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/VersionResolution.java
@@ -9,6 +9,7 @@ package org.hibernate.boot.model.process.internal;
import java.util.function.Function;
import jakarta.persistence.TemporalType;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.mapping.JdbcMapping;
@@ -57,6 +58,11 @@ public class VersionResolution implements BasicValue.Resolution {
// if it is a temporal version, it needs to be a TIMESTAMP
return TemporalType.TIMESTAMP;
}
+
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return context.getBuildingOptions().getDefaultTimeZoneStorage();
+ }
}
);
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java
index f6cdf8d96f..04f0428435 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java
@@ -6,11 +6,15 @@
*/
package org.hibernate.boot.model.process.spi;
+import java.sql.Types;
+import java.time.OffsetDateTime;
+import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
@@ -42,9 +46,10 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.CustomType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
-import org.hibernate.type.descriptor.java.JavaTypedExpressable;
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
+import org.hibernate.type.internal.NamedBasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserType;
@@ -420,5 +425,37 @@ public class MetadataBuildingProcess {
// add explicit application registered types
bootstrapContext.getTypeConfiguration()
.addBasicTypeRegistrationContributions( options.getBasicTypeRegistrations() );
+
+ // For NORMALIZE, we replace the standard types that use TIMESTAMP_WITH_TIMEZONE to use TIMESTAMP
+ if ( options.getDefaultTimeZoneStorage() == TimeZoneStorageStrategy.NORMALIZE ) {
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = bootstrapContext.getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
+ final JavaTypeDescriptorRegistry javaTypeRegistry = bootstrapContext.getTypeConfiguration()
+ .getJavaTypeDescriptorRegistry();
+ final JdbcTypeDescriptor timestampDescriptor = jdbcTypeRegistry.getDescriptor( Types.TIMESTAMP );
+ final BasicTypeRegistry basicTypeRegistry = bootstrapContext.getTypeConfiguration().getBasicTypeRegistry();
+ final BasicType> offsetDateTimeType = new NamedBasicTypeImpl<>(
+ javaTypeRegistry.getDescriptor( OffsetDateTime.class ),
+ timestampDescriptor,
+ "OffsetDateTime"
+ );
+ final BasicType> zonedDateTimeType = new NamedBasicTypeImpl<>(
+ javaTypeRegistry.getDescriptor( ZonedDateTime.class ),
+ timestampDescriptor,
+ "ZonedDateTime"
+ );
+ basicTypeRegistry.register(
+ offsetDateTimeType,
+ "org.hibernate.type.OffsetDateTimeType",
+ OffsetDateTime.class.getSimpleName(),
+ OffsetDateTime.class.getName()
+ );
+ basicTypeRegistry.register(
+ zonedDateTimeType,
+ "org.hibernate.type.ZonedDateTimeType",
+ ZonedDateTime.class.getSimpleName(),
+ ZonedDateTime.class.getName()
+ );
+ }
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuildingOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuildingOptions.java
index 3e215929e6..c34b9ad5d4 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuildingOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuildingOptions.java
@@ -11,6 +11,7 @@ import jakarta.persistence.SharedCacheMode;
import org.hibernate.HibernateException;
import org.hibernate.MultiTenancyStrategy;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
@@ -55,6 +56,11 @@ public abstract class AbstractDelegatingMetadataBuildingOptions implements Metad
return delegate.getMappingDefaults();
}
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
+ return delegate.getDefaultTimeZoneStorage();
+ }
+
@Override
public List getBasicTypeRegistrations() {
return delegate.getBasicTypeRegistrations();
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
index 8533f25b79..97de9df9aa 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
@@ -17,6 +17,7 @@ import org.hibernate.EntityNameResolver;
import org.hibernate.Interceptor;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.SessionFactoryObserver;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.SchemaAutoTooling;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.boot.registry.StandardServiceRegistry;
@@ -468,4 +469,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
public int getPreferredSqlTypeCodeForBoolean() {
return delegate.getPreferredSqlTypeCodeForBoolean();
}
+
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return delegate.getDefaultTimeZoneStorageStrategy();
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java
index a5f96b5c67..b0a64d986e 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java
@@ -10,6 +10,7 @@ import java.util.List;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.MultiTenancyStrategy;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
@@ -52,6 +53,8 @@ public interface MetadataBuildingOptions {
*/
MappingDefaults getMappingDefaults();
+ TimeZoneStorageStrategy getDefaultTimeZoneStorage();
+
default ManagedTypeRepresentationResolver getManagedTypeRepresentationResolver() {
// for now always return the standard one
return ManagedTypeRepresentationResolverStandard.INSTANCE;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
index d7ad0962a6..6bfb5b603f 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
@@ -17,6 +17,7 @@ import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MultiTenancyStrategy;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.query.NullPrecedence;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.SchemaAutoTooling;
@@ -348,4 +349,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
boolean isOmitJoinOfSuperclassTablesEnabled();
int getPreferredSqlTypeCodeForBoolean();
+
+ TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
index 5bf01e072b..b03ddee24f 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
@@ -2383,7 +2383,6 @@ public interface AvailableSettings {
*/
String OMIT_JOIN_OF_SUPERCLASS_TABLES = "hibernate.query.omit_join_of_superclass_tables";
-
/**
* Global setting identifying the preferred JDBC type code for storing
* boolean values. The fallback is to ask the Dialect
@@ -2392,6 +2391,21 @@ public interface AvailableSettings {
*/
String PREFERRED_BOOLEAN_JDBC_TYPE_CODE = "hibernate.type.perferred_boolean_jdbc_type_code";
+ /**
+ * Global setting for configuring the default storage for the time zone information for time zone based types.
+ *
+ * Possible values are {@link org.hibernate.annotations.TimeZoneStorageType#NORMALIZE},
+ * {@link org.hibernate.annotations.TimeZoneStorageType#COLUMN},
+ * {@link org.hibernate.annotations.TimeZoneStorageType#NATIVE}
+ * and {@link org.hibernate.annotations.TimeZoneStorageType#AUTO}.
+ *
+ * The default value is given by the {@link org.hibernate.annotations.TimeZoneStorageType#NORMALIZE},
+ * meaning that time zone information is not stored by default, but timestamps are normalized instead.
+ *
+ * @since 6.0
+ */
+ String TIMEZONE_DEFAULT_STORAGE = "hibernate.timezone.default_storage";
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Java (javax) Persistence defined settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
index 0f84e6b306..a47da9529a 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
@@ -17,6 +17,7 @@ import java.util.function.Function;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.AnyDiscriminator;
import org.hibernate.annotations.AnyKeyJavaClass;
import org.hibernate.annotations.AnyKeyJavaType;
@@ -190,6 +191,10 @@ public class BasicValueBinder implements JdbcTypeDescriptorIndicators {
public TypeConfiguration getTypeConfiguration() {
return buildingContext.getBootstrapContext().getTypeConfiguration();
}
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return buildingContext.getBuildingOptions().getDefaultTimeZoneStorage();
+ }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java
index 3bbccfb1e0..dc640e7667 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java
@@ -141,8 +141,8 @@ public class CockroachDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NORMALIZE;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java
index c21f7eb6e1..d0f75ca750 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java
@@ -54,8 +54,8 @@ public class DB2zDialect extends DB2Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return getZVersion() > 1000;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return getZVersion() > 1000 ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
}
int getZVersion() {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
index af878d1582..3089b19ac2 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
@@ -3726,10 +3726,10 @@ public abstract class Dialect implements ConversionContext {
}
/**
- * Whether the Dialect supports timezone types like {@link Types#TIMESTAMP_WITH_TIMEZONE}.
+ * How the Dialect supports time zone types like {@link Types#TIMESTAMP_WITH_TIMEZONE}.
*/
- public boolean supportsTimezoneTypes() {
- return false;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NONE;
}
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
index 06feebbe6b..5a82d81d0d 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
@@ -52,6 +52,7 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
+
import org.jboss.logging.Logger;
import static org.hibernate.query.TemporalUnit.SECOND;
@@ -147,6 +148,11 @@ public class H2Dialect extends Dialect {
);
}
+ public boolean hasDstBug() {
+ // H2 1.4.200 has a bug: https://github.com/h2database/h2database/issues/3184
+ return getVersion() == 104200;
+ }
+
@Override
public int getVersion() {
return version;
@@ -265,8 +271,8 @@ public class H2Dialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NATIVE;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
index 81ad42e971..f976ed3f69 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java
@@ -567,8 +567,8 @@ public class OracleDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return getVersion() >= 900;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return getVersion() >= 900 ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
}
protected void registerBinaryTypeMappings() {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
index 3c216f97d0..a74ade1b96 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java
@@ -69,7 +69,6 @@ import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.BlobJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.ClobJdbcTypeDescriptor;
-import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
@@ -287,8 +286,8 @@ public class PostgreSQLDialect extends Dialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return true;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return TimeZoneSupport.NORMALIZE;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
index 0b1e1e4f3f..466dff9bce 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
@@ -149,8 +149,8 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
}
@Override
- public boolean supportsTimezoneTypes() {
- return getVersion() >= 10;
+ public TimeZoneSupport getTimeZoneSupport() {
+ return getVersion() >= 10 ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java
index 4bf5f79b8b..c953165ab9 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java
@@ -45,7 +45,6 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.NClobJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.SmallIntJdbcTypeDescriptor;
-import org.hibernate.type.descriptor.jdbc.TinyIntJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import java.sql.DatabaseMetaData;
@@ -172,9 +171,10 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
// The jTDS driver doesn't support the JDBC4 signatures using 'long length' for stream bindings
jdbcTypeRegistry.addDescriptor( Types.CLOB, ClobJdbcTypeDescriptor.CLOB_BINDING );
- jdbcTypeRegistry.addDescriptor( Types.NCLOB, NClobJdbcTypeDescriptor.NCLOB_BINDING );
- // The jTDS driver doesn't support the JDBC4 setNString method
- jdbcTypeRegistry.addDescriptor( Types.NVARCHAR, NClobJdbcTypeDescriptor.NCLOB_BINDING );
+
+ // The jTDS driver doesn't support nationalized types
+ jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcTypeDescriptor.CLOB_BINDING );
+ jdbcTypeRegistry.addDescriptor( Types.NVARCHAR, ClobJdbcTypeDescriptor.CLOB_BINDING );
}
else {
// Some Sybase drivers cannot support getClob. See HHH-7889
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TimeZoneSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/TimeZoneSupport.java
new file mode 100644
index 0000000000..3810828862
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/TimeZoneSupport.java
@@ -0,0 +1,30 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or .
+ */
+package org.hibernate.dialect;
+
+import org.hibernate.Incubating;
+
+/**
+ * Describes the support for "with time zone" types.
+ *
+ * @author Christian Beikov
+ */
+@Incubating
+public enum TimeZoneSupport {
+ /**
+ * The "with time zone" types retain the time zone information.
+ */
+ NATIVE,
+ /**
+ * The "with time zone" types normalize to UTC.
+ */
+ NORMALIZE,
+ /**
+ * No support for "with time zone" types.
+ */
+ NONE;
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java
index b86f7dce22..d14c71b6b8 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java
@@ -17,6 +17,7 @@ import jakarta.persistence.PessimisticLockScope;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
@@ -66,7 +67,6 @@ import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.LockOptionsHelper;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor;
-import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_SCOPE;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_TIMEOUT;
@@ -147,6 +147,7 @@ public final class FastSessionServices {
final boolean disallowOutOfTransactionUpdateOperations;
final boolean useStreamForLobBinding;
final int preferredSqlTypeCodeForBoolean;
+ final TimeZoneStorageStrategy defaultTimeZoneStorageStrategy;
final boolean requiresMultiTenantConnectionProvider;
final ConnectionProvider connectionProvider;
final MultiTenantConnectionProvider multiTenantConnectionProvider;
@@ -216,6 +217,7 @@ public final class FastSessionServices {
this.disallowOutOfTransactionUpdateOperations = !sessionFactoryOptions.isAllowOutOfTransactionUpdateOperations();
this.useStreamForLobBinding = Environment.useStreamsForBinary() || dialect.useInputStreamToInsertBlob();
this.preferredSqlTypeCodeForBoolean = sessionFactoryOptions.getPreferredSqlTypeCodeForBoolean();
+ this.defaultTimeZoneStorageStrategy = sessionFactoryOptions.getDefaultTimeZoneStorageStrategy();
this.requiresMultiTenantConnectionProvider = sf.getSettings().getMultiTenancyStrategy().requiresMultiTenantConnectionProvider();
//Some "hot" services:
@@ -361,4 +363,8 @@ public final class FastSessionServices {
public int getPreferredSqlTypeCodeForBoolean() {
return preferredSqlTypeCodeForBoolean;
}
+
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return defaultTimeZoneStorageStrategy;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
index 5de97d67cc..95440bddfc 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
@@ -12,6 +12,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import org.hibernate.MappingException;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.TypeDefinitionRegistry;
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
@@ -68,7 +69,6 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
private static final CoreMessageLogger log = CoreLogging.messageLogger( BasicValue.class );
private final TypeConfiguration typeConfiguration;
- private final int preferredJdbcTypeCodeForBoolean;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// incoming "configuration" values
@@ -102,7 +102,6 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
super( buildingContext, table );
this.typeConfiguration = buildingContext.getBootstrapContext().getTypeConfiguration();
- this.preferredJdbcTypeCodeForBoolean = buildingContext.getPreferredSqlTypeCodeForBoolean();
buildingContext.getMetadataCollector().registerValueMappingResolver( this::resolve );
}
@@ -600,7 +599,12 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
@Override
public int getPreferredSqlTypeCodeForBoolean() {
- return preferredJdbcTypeCodeForBoolean;
+ return getBuildingContext().getPreferredSqlTypeCodeForBoolean();
+ }
+
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return getBuildingContext().getBuildingOptions().getDefaultTimeZoneStorage();
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java
index 932b83732b..b3a212a503 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java
@@ -20,6 +20,7 @@ import jakarta.persistence.AttributeConverter;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
+import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
@@ -33,7 +34,6 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
-import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentityGenerator;
@@ -53,6 +53,7 @@ import org.hibernate.type.descriptor.converter.AttributeConverterJdbcTypeDescrip
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
import org.hibernate.type.descriptor.java.BasicJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
+import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
import org.hibernate.type.descriptor.jdbc.LobTypeMappings;
import org.hibernate.type.descriptor.jdbc.NationalizedTypeMappings;
import org.hibernate.type.spi.TypeConfiguration;
@@ -668,7 +669,17 @@ public abstract class SimpleValue implements KeyValue {
// VARCHAR/CHAR
final JdbcTypeDescriptor recommendedJdbcType = jpaAttributeConverter.getRelationalJavaTypeDescriptor().getRecommendedJdbcType(
// todo (6.0) : handle the other JdbcRecommendedSqlTypeMappingContext methods
- metadata::getTypeConfiguration
+ new JdbcTypeDescriptorIndicators() {
+ @Override
+ public TypeConfiguration getTypeConfiguration() {
+ return metadata.getTypeConfiguration();
+ }
+
+ @Override
+ public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
+ return buildingContext.getBuildingOptions().getDefaultTimeZoneStorage();
+ }
+ }
);
int jdbcTypeCode = recommendedJdbcType.getJdbcTypeCode();
if ( isLob() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java b/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java
index bfbcd78402..b99debfb02 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java
@@ -388,7 +388,8 @@ public final class StandardBasicTypes {
);
/**
- * The standard Hibernate type for mapping {@link OffsetDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}.
+ * The standard Hibernate type for mapping {@link OffsetDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}
+ * or {@link java.sql.Types#TIMESTAMP TIMESTAMP} depending on the {@link org.hibernate.cfg.AvailableSettings#TIMEZONE_DEFAULT_STORAGE} setting.
*/
public static final BasicTypeReference OFFSET_DATE_TIME = new BasicTypeReference<>(
"OffsetDateTime",
@@ -396,18 +397,36 @@ public final class StandardBasicTypes {
Types.TIMESTAMP_WITH_TIMEZONE
);
+ /**
+ * The standard Hibernate type for mapping {@link OffsetDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}.
+ */
+ public static final BasicTypeReference OFFSET_DATE_TIME_WITH_TIMEZONE = new BasicTypeReference<>(
+ "OffsetDateTimeWithTimezone",
+ OffsetDateTime.class,
+ Types.TIMESTAMP_WITH_TIMEZONE
+ );
+ /**
+ * The standard Hibernate type for mapping {@link OffsetDateTime} to JDBC {@link java.sql.Types#TIMESTAMP TIMESTAMP}.
+ */
+ public static final BasicTypeReference OFFSET_DATE_TIME_WITHOUT_TIMEZONE = new BasicTypeReference<>(
+ "OffsetDateTimeWithoutTimezone",
+ OffsetDateTime.class,
+ Types.TIMESTAMP
+ );
+
/**
* The standard Hibernate type for mapping {@link OffsetTime} to JDBC {@link java.sql.Types#TIME TIME}.
*/
public static final BasicTypeReference OFFSET_TIME = new BasicTypeReference<>(
- "ZonedDateTime",
+ "OffsetTime",
OffsetTime.class,
// todo (6.0): why not TIME_WITH_TIMEZONE ?
Types.TIME
);
/**
- * The standard Hibernate type for mapping {@link ZonedDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}.
+ * The standard Hibernate type for mapping {@link ZonedDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}
+ * or {@link java.sql.Types#TIMESTAMP TIMESTAMP} depending on the {@link org.hibernate.cfg.AvailableSettings#TIMEZONE_DEFAULT_STORAGE} setting.
*/
public static final BasicTypeReference ZONED_DATE_TIME = new BasicTypeReference<>(
"ZonedDateTime",
@@ -415,6 +434,24 @@ public final class StandardBasicTypes {
Types.TIMESTAMP_WITH_TIMEZONE
);
+ /**
+ * The standard Hibernate type for mapping {@link ZonedDateTime} to JDBC {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE}.
+ */
+ public static final BasicTypeReference ZONED_DATE_TIME_WITH_TIMEZONE = new BasicTypeReference<>(
+ "ZonedDateTimeWithTimezone",
+ ZonedDateTime.class,
+ Types.TIMESTAMP_WITH_TIMEZONE
+ );
+
+ /**
+ * The standard Hibernate type for mapping {@link ZonedDateTime} to JDBC {@link java.sql.Types#TIMESTAMP TIMESTAMP}.
+ */
+ public static final BasicTypeReference ZONED_DATE_TIME_WITHOUT_TIMEZONE = new BasicTypeReference<>(
+ "ZonedDateTimeWithoutTimezone",
+ ZonedDateTime.class,
+ Types.TIMESTAMP
+ );
+
/**
* The standard Hibernate type for mapping {@link Instant} to JDBC
* {@link java.sql.Types#TIMESTAMP TIMESTAMP}.
diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaTypeDescriptor.java
index e6d7ba560c..13e914518b 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaTypeDescriptor.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaTypeDescriptor.java
@@ -6,6 +6,7 @@
*/
package org.hibernate.type.descriptor.java;
+import java.sql.Types;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
@@ -40,7 +41,7 @@ public class CalendarDateJavaTypeDescriptor extends AbstractTemporalJavaTypeDesc
@Override
public JdbcTypeDescriptor getRecommendedJdbcType(JdbcTypeDescriptorIndicators context) {
- return DateJdbcTypeDescriptor.INSTANCE;
+ return context.getTypeConfiguration().getJdbcTypeDescriptorRegistry().getDescriptor( Types.DATE );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaTypeDescriptor.java
index ab4e511c88..0b098587a4 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaTypeDescriptor.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaTypeDescriptor.java
@@ -6,6 +6,7 @@
*/
package org.hibernate.type.descriptor.java;
+import java.sql.Types;
import java.util.Calendar;
import java.util.Comparator;
import java.util.GregorianCalendar;
@@ -49,7 +50,7 @@ public class CalendarJavaTypeDescriptor extends AbstractTemporalJavaTypeDescript
@Override
public JdbcTypeDescriptor getRecommendedJdbcType(JdbcTypeDescriptorIndicators context) {
- return TimestampJdbcTypeDescriptor.INSTANCE;
+ return context.getTypeConfiguration().getJdbcTypeDescriptorRegistry().getDescriptor( Types.TIMESTAMP );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaTypeDescriptor.java
index 213df3d3b9..996df8bdeb 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaTypeDescriptor.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaTypeDescriptor.java
@@ -6,6 +6,7 @@
*/
package org.hibernate.type.descriptor.java;
+import java.sql.Types;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
@@ -40,7 +41,7 @@ public class CalendarTimeJavaTypeDescriptor extends AbstractTemporalJavaTypeDesc
@Override
public JdbcTypeDescriptor getRecommendedJdbcType(JdbcTypeDescriptorIndicators context) {
- return TimeJdbcTypeDescriptor.INSTANCE;
+ return context.getTypeConfiguration().getJdbcTypeDescriptorRegistry().getDescriptor( Types.TIME );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaTypeDescriptor.java
index cf499ce2b1..adf24dc02a 100644
--- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaTypeDescriptor.java
+++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaTypeDescriptor.java
@@ -7,6 +7,7 @@
package org.hibernate.type.descriptor.java;
import java.sql.Timestamp;
+import java.sql.Types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -57,7 +58,7 @@ public class DateJavaTypeDescriptor extends AbstractTemporalJavaTypeDescriptor) prop.getType();
assertSame( StringJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- // See issue HHH-10693
- if ( dialect instanceof SybaseDialect ) {
- assertSame( ClobJdbcTypeDescriptor.CLOB_BINDING, type.getJdbcTypeDescriptor() );
- }
- else {
- assertSame( ClobJdbcTypeDescriptor.DEFAULT, type.getJdbcTypeDescriptor() );
- }
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.CLOB ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( NClobJdbcTypeDescriptor.DEFAULT, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.NCLOB ), type.getJdbcTypeDescriptor() );
}
prop = pc.getProperty( "nclobAtt" );
type = (BasicType>) prop.getType();
assertSame( NClobJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- // See issue HHH-10693
- if ( dialect instanceof SybaseDialect ) {
- assertSame( ClobJdbcTypeDescriptor.CLOB_BINDING, type.getJdbcTypeDescriptor() );
- }
- else {
- assertSame( ClobJdbcTypeDescriptor.DEFAULT, type.getJdbcTypeDescriptor() );
- }
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.CLOB ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( NClobJdbcTypeDescriptor.DEFAULT, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.NCLOB ), type.getJdbcTypeDescriptor() );
}
prop = pc.getProperty( "nlongvarcharcharAtt" );
- {
- final BasicValue.Resolution> resolution = ( (BasicValue) prop.getValue() ).resolve();
-
- final int jdbcTypeExpected;
- if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- jdbcTypeExpected = Types.CLOB;
- }
- else {
- jdbcTypeExpected = Types.NCLOB;
- }
- Assertions.assertThat( resolution.getJdbcTypeDescriptor().getJdbcTypeCode() ).isEqualTo( jdbcTypeExpected );
+ type = (BasicType>) prop.getType();
+ assertSame( StringJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
+ if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.CLOB ), type.getJdbcTypeDescriptor() );
+ }
+ else {
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.NCLOB ), type.getJdbcTypeDescriptor() );
}
prop = pc.getProperty( "ncharArrAtt" );
type = (BasicType>) prop.getType();
assertSame( CharacterArrayJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- // See issue HHH-10693
- assertSame( VarcharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.VARCHAR ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( NVarcharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.NVARCHAR ), type.getJdbcTypeDescriptor() );
}
prop = pc.getProperty( "ncharacterAtt" );
type = (BasicType>) prop.getType();
assertSame( CharacterJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- // See issue HHH-10693
- assertSame( CharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.CHAR ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( NCharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ assertSame( jdbcTypeRegistry.getDescriptor( Types.NCHAR ), type.getJdbcTypeDescriptor() );
}
}
finally {
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/nationalized/UseNationalizedCharDataSettingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/nationalized/UseNationalizedCharDataSettingTest.java
index d526bef3af..71ac8d18c9 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/nationalized/UseNationalizedCharDataSettingTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/nationalized/UseNationalizedCharDataSettingTest.java
@@ -6,6 +6,8 @@
*/
package org.hibernate.orm.test.nationalized;
+import java.sql.Types;
+
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@@ -27,10 +29,12 @@ import org.hibernate.type.descriptor.jdbc.CharJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.NCharJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.NVarcharJdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.VarcharJdbcTypeDescriptor;
+import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
import static org.junit.Assert.assertSame;
@@ -53,18 +57,19 @@ public class UseNationalizedCharDataSettingTest extends BaseUnitTestCase {
ms.addAnnotatedClass( NationalizedBySettingEntity.class );
final Metadata metadata = ms.buildMetadata();
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = metadata.getDatabase()
+ .getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
final PersistentClass pc = metadata.getEntityBinding( NationalizedBySettingEntity.class.getName() );
final Property nameAttribute = pc.getProperty( "name" );
final BasicType> type = (BasicType>) nameAttribute.getType();
final Dialect dialect = metadata.getDatabase().getDialect();
+ assertSame( StringJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- // See issue HHH-10693
- assertSame( StringJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
- assertSame( VarcharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ Assertions.assertSame( jdbcTypeRegistry.getDescriptor( Types.VARCHAR ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( StringJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
- assertSame( NVarcharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ Assertions.assertSame( jdbcTypeRegistry.getDescriptor( Types.NVARCHAR ), type.getJdbcTypeDescriptor() );
}
}
@@ -85,17 +90,19 @@ public class UseNationalizedCharDataSettingTest extends BaseUnitTestCase {
ms.addAnnotatedClass( NationalizedBySettingEntity.class );
final Metadata metadata = ms.buildMetadata();
+ final JdbcTypeDescriptorRegistry jdbcTypeRegistry = metadata.getDatabase()
+ .getTypeConfiguration()
+ .getJdbcTypeDescriptorRegistry();
final PersistentClass pc = metadata.getEntityBinding( NationalizedBySettingEntity.class.getName() );
final Property nameAttribute = pc.getProperty( "flag" );
final BasicType> type = (BasicType>) nameAttribute.getType();
final Dialect dialect = metadata.getDatabase().getDialect();
+ assertSame( CharacterJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
if ( dialect.getNationalizationSupport() != NationalizationSupport.EXPLICIT ) {
- assertSame( CharacterJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
- assertSame( CharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ Assertions.assertSame( jdbcTypeRegistry.getDescriptor( Types.CHAR ), type.getJdbcTypeDescriptor() );
}
else {
- assertSame( CharacterJavaTypeDescriptor.INSTANCE, type.getJavaTypeDescriptor() );
- assertSame( NCharJdbcTypeDescriptor.INSTANCE, type.getJdbcTypeDescriptor() );
+ Assertions.assertSame( jdbcTypeRegistry.getDescriptor( Types.NCHAR ), type.getJdbcTypeDescriptor() );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/AbstractJavaTimeTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java
similarity index 93%
rename from hibernate-core/src/test/java/org/hibernate/test/type/AbstractJavaTimeTypeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java
index 075768d041..b92f96605a 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/AbstractJavaTimeTypeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -20,6 +20,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.cfg.AvailableSettings;
@@ -27,7 +28,6 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.service.ServiceRegistry;
-import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@@ -47,7 +47,7 @@ import static org.junit.Assert.assertEquals;
* @param The entity type used in tests.
*/
@RunWith(CustomParameterized.class)
-abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase {
+public abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase {
private static Dialect determineDialect() {
try {
@@ -287,6 +287,13 @@ abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase
return thisAsS();
}
+ public S skippedForDialects(Predicate skipPredicate, Consumer skippedIfDialectMatchesClasses) {
+ if ( !skipPredicate.test( dialect ) ) {
+ skippedIfDialectMatchesClasses.accept( thisAsS() );
+ }
+ return thisAsS();
+ }
+
public S withForcedJdbcTimezone(String zoneIdString, Consumer contributor) {
ZoneId zoneId = ZoneId.of( zoneIdString );
this.forcedJdbcTimeZone = zoneId;
@@ -301,7 +308,7 @@ abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase
@SafeVarargs
public final S alsoTestRemappingsWithH2(Class extends AbstractRemappingH2Dialect> ... dialectClasses) {
- if ( dialect instanceof H2Dialect ) {
+ if ( dialect instanceof H2Dialect && !( (H2Dialect) dialect ).hasDstBug() ) {
// Only test remappings with H2
Collections.addAll( remappingDialectClasses, dialectClasses );
}
@@ -395,11 +402,12 @@ abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase
protected static class AbstractRemappingH2Dialect extends H2Dialect {
private final int overriddenSqlTypeCode;
- private final JdbcTypeDescriptor overriddenJdbcTypeDescriptor;
+ private final int overridingSqlTypeCode;
- public AbstractRemappingH2Dialect(int overriddenSqlTypeCode, JdbcTypeDescriptor overriddenJdbcTypeDescriptor) {
+ public AbstractRemappingH2Dialect(int overriddenSqlTypeCode, int overridingSqlTypeCode) {
+ super( getDialect().getVersion() );
this.overriddenSqlTypeCode = overriddenSqlTypeCode;
- this.overriddenJdbcTypeDescriptor = overriddenJdbcTypeDescriptor;
+ this.overridingSqlTypeCode = overridingSqlTypeCode;
}
@Override
@@ -408,7 +416,9 @@ abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalTestCase
typeContributions.getTypeConfiguration().getJdbcTypeDescriptorRegistry().addDescriptor(
overriddenSqlTypeCode,
- overriddenJdbcTypeDescriptor
+ typeContributions.getTypeConfiguration().getJdbcTypeDescriptorRegistry().getDescriptor(
+ overridingSqlTypeCode
+ )
);
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/BigDecimalTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/BigDecimalTypeTest.java
similarity index 98%
rename from hibernate-core/src/test/java/org/hibernate/test/type/BigDecimalTypeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/BigDecimalTypeTest.java
index 9c6dac54b1..198ff92932 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/BigDecimalTypeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/BigDecimalTypeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import org.hibernate.Session;
import org.hibernate.query.Query;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/BinaryTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/BinaryTypeTest.java
similarity index 98%
rename from hibernate-core/src/test/java/org/hibernate/test/type/BinaryTypeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/BinaryTypeTest.java
index 3b4107dd38..8f9ea93edf 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/BinaryTypeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/BinaryTypeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/InstantTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/InstantTest.java
similarity index 88%
rename from hibernate-core/src/test/java/org/hibernate/test/type/InstantTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/InstantTest.java
index edb91a849d..5d16c7bf11 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/InstantTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/InstantTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -22,8 +22,10 @@ import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
+import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
+import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.dialect.SybaseDialect;
import org.junit.runners.Parameterized;
@@ -61,21 +63,26 @@ public class InstantTest extends AbstractJavaTimeTypeTest dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect
+ || dialect instanceof SybaseDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
b -> b
.add( 1600, 1, 1, 0, 0, 0, 0, ZONE_AMSTERDAM )
+ // Affected by HHH-13266 (JDK-8061577)
+ .add( 1892, 1, 1, 0, 0, 0, 0, ZONE_OSLO )
)
// HHH-13379: DST end (where Timestamp becomes ambiguous, see JDK-4312621)
// => This used to work correctly in 5.4.1.Final and earlier
- .add( 2018, 10, 28, 1, 0, 0, 0, ZONE_PARIS )
- .add( 2018, 3, 31, 14, 0, 0, 0, ZONE_AUCKLAND )
+ .skippedForDialects(
+ dialect -> dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b.add( 2018, 10, 28, 1, 0, 0, 0, ZONE_PARIS )
+ .add( 2018, 3, 31, 14, 0, 0, 0, ZONE_AUCKLAND )
+ )
// => This has never worked correctly, unless the JDBC timezone was set to UTC
.withForcedJdbcTimezone( "UTC", b -> b
.add( 2018, 10, 28, 0, 0, 0, 0, ZONE_PARIS )
@@ -83,8 +90,12 @@ public class InstantTest extends AbstractJavaTimeTypeTest Also test DST start, just in case
.add( 2018, 3, 25, 1, 0, 0, 0, ZONE_PARIS )
- .add( 2018, 3, 25, 2, 0, 0, 0, ZONE_PARIS )
- .add( 2018, 9, 30, 2, 0, 0, 0, ZONE_AUCKLAND )
+ .skippedForDialects(
+ // No idea what Sybase is doing here exactly
+ dialect -> dialect instanceof SybaseASEDialect,
+ b -> b.add( 2018, 3, 25, 2, 0, 0, 0, ZONE_PARIS )
+ .add( 2018, 9, 30, 2, 0, 0, 0, ZONE_AUCKLAND )
+ )
.add( 2018, 9, 30, 3, 0, 0, 0, ZONE_AUCKLAND )
// => Also test dates around 1905-01-01, because the code behaves differently before and after 1905
.add( 1904, 12, 31, 22, 59, 59, 999_999_999, ZONE_PARIS )
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/Java8DateTimeTests.java
similarity index 99%
rename from hibernate-core/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/Java8DateTimeTests.java
index d9f8d54cc5..938720edf2 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/Java8DateTimeTests.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.time.Duration;
import java.time.Instant;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/LobUnfetchedPropertyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LobUnfetchedPropertyTest.java
similarity index 99%
rename from hibernate-core/src/test/java/org/hibernate/test/type/LobUnfetchedPropertyTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/LobUnfetchedPropertyTest.java
index ec9f85b1b6..1ae945bb9d 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/LobUnfetchedPropertyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LobUnfetchedPropertyTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertFalse;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/LocalDateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalDateTest.java
similarity index 89%
rename from hibernate-core/src/test/java/org/hibernate/test/type/LocalDateTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalDateTest.java
index 55f6457303..1f8427dc8d 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/LocalDateTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalDateTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.Date;
import java.sql.PreparedStatement;
@@ -22,10 +22,11 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.dialect.AbstractHANADialect;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect;
-import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.MySQLDialect;
-import org.hibernate.type.descriptor.jdbc.TimestampJdbcTypeDescriptor;
+import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
@@ -37,11 +38,13 @@ import org.junit.runners.Parameterized;
@TestForIssue(jiraKey = "HHH-10371")
@SkipForDialect(value = AbstractHANADialect.class,
comment = "HANA systematically returns the wrong date when the JVM default timezone is not UTC")
-@SkipForDialect(value = MySQL5Dialect.class,
+@SkipForDialect(value = MySQLDialect.class,
comment = "HHH-13582: MySQL ConnectorJ 8.x returns the wrong date"
+ " when the JVM default timezone is different from the server timezone:"
+ " https://bugs.mysql.com/bug.php?id=91112"
)
+@SkipForDialect(value = H2Dialect.class, comment = "H2 1.4.200 DST bug. See org.hibernate.dialect.H2Dialect.hasDstBug")
+@SkipForDialect(value = HSQLDialect.class, comment = "HSQL has problems with DST edges")
public class LocalDateTest extends AbstractJavaTimeTypeTest {
private static class ParametersBuilder extends AbstractParametersBuilder {
@@ -70,7 +73,11 @@ public class LocalDateTest extends AbstractJavaTimeTypeTest dialect instanceof SybaseASEDialect,
+ b -> b.add( 1600, 1, 1, ZONE_AMSTERDAM )
)
// HHH-13379: DST end (where Timestamp becomes ambiguous, see JDK-4312621)
// It doesn't seem that any date at midnight can be affected by HHH-13379, but we add some tests just in case
@@ -167,7 +174,7 @@ public class LocalDateTest extends AbstractJavaTimeTypeTest dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b
+ // Affected by HHH-13266 (JDK-8061577)
+ .add( 1892, 1, 1, 0, 0, 0, 0, ZONE_OSLO )
+ )
.skippedForDialects(
// MySQL/Mariadb/Sybase cannot store dates in 1600 in a timestamp.
- Arrays.asList( MySQLDialect.class, MariaDBDialect.class, SybaseDialect.class ),
+ dialect -> dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect || dialect instanceof SybaseDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
b -> b
.add( 1600, 1, 1, 0, 0, 0, 0, ZONE_AMSTERDAM )
)
// HHH-13379: DST end (where Timestamp becomes ambiguous, see JDK-4312621)
// It doesn't seem that any LocalDateTime can be affected by HHH-13379, but we add some tests just in case
.add( 2018, 10, 28, 1, 0, 0, 0, ZONE_PARIS )
- .add( 2018, 10, 28, 2, 0, 0, 0, ZONE_PARIS )
+ .skippedForDialects(
+ dialect -> dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b
+ .add( 2018, 10, 28, 2, 0, 0, 0, ZONE_PARIS )
+ )
.add( 2018, 10, 28, 3, 0, 0, 0, ZONE_PARIS )
.add( 2018, 10, 28, 4, 0, 0, 0, ZONE_PARIS )
.add( 2018, 4, 1, 1, 0, 0, 0, ZONE_AUCKLAND )
- .add( 2018, 4, 1, 2, 0, 0, 0, ZONE_AUCKLAND )
+ .skippedForDialects(
+ dialect -> dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b
+ .add( 2018, 4, 1, 2, 0, 0, 0, ZONE_AUCKLAND )
+ )
.add( 2018, 4, 1, 3, 0, 0, 0, ZONE_AUCKLAND )
.add( 2018, 4, 1, 4, 0, 0, 0, ZONE_AUCKLAND )
// => Also test DST start
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/LocalTimeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalTimeTest.java
similarity index 95%
rename from hibernate-core/src/test/java/org/hibernate/test/type/LocalTimeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalTimeTest.java
index 221214bbea..9243d1012c 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/LocalTimeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/LocalTimeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -23,10 +23,10 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.dialect.AbstractHANADialect;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect;
-import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.MySQLDialect;
-import org.hibernate.type.descriptor.jdbc.TimestampJdbcTypeDescriptor;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
@@ -35,6 +35,7 @@ import org.junit.runners.Parameterized;
/**
* Tests for storage of LocalTime properties.
*/
+@SkipForDialect(value = H2Dialect.class, comment = "H2 1.4.200 DST bug. See org.hibernate.dialect.H2Dialect.hasDstBug")
public class LocalTimeTest extends AbstractJavaTimeTypeTest {
private static class ParametersBuilder extends AbstractParametersBuilder {
@@ -200,12 +201,13 @@ public class LocalTimeTest extends AbstractJavaTimeTypeTest.
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -22,11 +22,11 @@ import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
+import org.hibernate.dialect.H2Dialect;
import org.hibernate.query.Query;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
-import org.hibernate.type.OffsetDateTimeType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.testing.TestForIssue;
@@ -88,22 +88,32 @@ public class OffsetDateTimeTest extends AbstractJavaTimeTypeTest dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b
+ // Affected by HHH-13266 (JDK-8061577)
+ .add( 1892, 1, 1, 0, 0, 0, 0, "+00:00", ZONE_OSLO )
+ )
.skippedForDialects(
// MySQL/Mariadb/Sybase cannot store dates in 1600 in a timestamp.
- Arrays.asList( MySQLDialect.class, MariaDBDialect.class, SybaseDialect.class ),
+ dialect -> dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect || dialect instanceof SybaseDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
b -> b
.add( 1600, 1, 1, 0, 0, 0, 0, "+00:19:32", ZONE_AMSTERDAM )
)
// HHH-13379: DST end (where Timestamp becomes ambiguous, see JDK-4312621)
// => This used to work correctly in 5.4.1.Final and earlier
- .add( 2018, 10, 28, 2, 0, 0, 0, "+01:00", ZONE_PARIS )
- .add( 2018, 4, 1, 2, 0, 0, 0, "+12:00", ZONE_AUCKLAND )
+ .skippedForDialects(
+ dialect -> dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b.add( 2018, 10, 28, 2, 0, 0, 0, "+01:00", ZONE_PARIS )
+ .add( 2018, 4, 1, 2, 0, 0, 0, "+12:00", ZONE_AUCKLAND )
+ )
// => This has never worked correctly, unless the JDBC timezone was set to UTC
.withForcedJdbcTimezone( "UTC", b -> b
.add( 2018, 10, 28, 2, 0, 0, 0, "+02:00", ZONE_PARIS )
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/OffsetTimeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/OffsetTimeTest.java
similarity index 96%
rename from hibernate-core/src/test/java/org/hibernate/test/type/OffsetTimeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/OffsetTimeTest.java
index 617cb92adc..4f17cf8cb4 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/OffsetTimeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/OffsetTimeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -25,11 +25,9 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.dialect.AbstractHANADialect;
+import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect;
-import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.MySQLDialect;
-import org.hibernate.type.descriptor.jdbc.BigIntJdbcTypeDescriptor;
-import org.hibernate.type.descriptor.jdbc.TimestampJdbcTypeDescriptor;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
@@ -229,12 +227,13 @@ public class OffsetTimeTest extends AbstractJavaTimeTypeTest.
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -17,35 +17,34 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
-import org.hibernate.dialect.SQLServer2008Dialect;
+import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
+import org.hibernate.testing.orm.junit.RequiresDialect;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
/**
* @author Andrea Boriero
*/
@TestForIssue(jiraKey = "HHH-10529")
-@RequiresDialect(value = SQLServer2008Dialect.class)
-public class SQLServer2008NVarCharTypeTest extends BaseUnitTestCase {
+@RequiresDialect(value = SQLServerDialect.class, version = 10)
+public class SQLServer2008NVarCharTypeTest {
private StandardServiceRegistry ssr;
private MetadataImplementor metadata;
private SchemaExport schemaExport;
- @Before
+ @BeforeEach
public void setUp() {
ssr = new StandardServiceRegistryBuilder().build();
schemaExport = createSchemaExport( new Class[] {MyEntity.class} );
}
- @After
+ @AfterEach
public void tearDown() {
schemaExport.drop( EnumSet.of( TargetType.DATABASE ), metadata );
StandardServiceRegistryBuilder.destroy( ssr );
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/SmallIntToShortClassMappingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/SmallIntToShortClassMappingTest.java
similarity index 98%
rename from hibernate-core/src/test/java/org/hibernate/test/type/SmallIntToShortClassMappingTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/SmallIntToShortClassMappingTest.java
index 14d211500d..cf00787d23 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/SmallIntToShortClassMappingTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/SmallIntToShortClassMappingTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Column;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/StandardBasicTypeTemplateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/StandardBasicTypeTemplateTest.java
similarity index 98%
rename from hibernate-core/src/test/java/org/hibernate/test/type/StandardBasicTypeTemplateTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/StandardBasicTypeTemplateTest.java
index b97172fe3c..c0d05e12f8 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/StandardBasicTypeTemplateTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/StandardBasicTypeTemplateTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.net.URL;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/TimeAndTimestampTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/TimeAndTimestampTest.java
similarity index 93%
rename from hibernate-core/src/test/java/org/hibernate/test/type/TimeAndTimestampTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/TimeAndTimestampTest.java
index 5a95470e2d..2164d1a950 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/TimeAndTimestampTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/TimeAndTimestampTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.Time;
import java.sql.Timestamp;
@@ -50,14 +50,14 @@ public class TimeAndTimestampTest extends BaseNonConfigCoreFunctionalTestCase {
Event event = new Event();
event.id = 1L;
event.timeValue = new Time( 1000 );
- event.timestampValue = new Timestamp( 45678 );
+ event.timestampValue = new Timestamp( 45677 );
session.persist( event );
} );
doInHibernate( this::sessionFactory, session -> {
Event event = session.find( Event.class, 1L );
assertEquals(1000, event.timeValue.getTime() % TimeUnit.DAYS.toMillis( 1 ));
- assertEquals(45678, event.timestampValue.getTime() % TimeUnit.DAYS.toMillis( 1 ));
+ assertEquals(45677, event.timestampValue.getTime() % TimeUnit.DAYS.toMillis( 1 ));
} );
}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/TypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/TypeTest.java
similarity index 99%
rename from hibernate-core/src/test/java/org/hibernate/test/type/TypeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/TypeTest.java
index 29ecd406dc..81cab1ec23 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/TypeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/TypeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/ZonedDateTimeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/ZonedDateTimeTest.java
similarity index 92%
rename from hibernate-core/src/test/java/org/hibernate/test/type/ZonedDateTimeTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/type/ZonedDateTimeTest.java
index 203556c7d3..9954758c75 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/type/ZonedDateTimeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/ZonedDateTimeTest.java
@@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
-package org.hibernate.test.type;
+package org.hibernate.orm.test.type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -22,12 +22,12 @@ import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
+import org.hibernate.dialect.H2Dialect;
import org.hibernate.query.Query;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.type.StandardBasicTypes;
-import org.hibernate.type.ZonedDateTimeType;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
@@ -96,26 +96,36 @@ public class ZonedDateTimeTest extends AbstractJavaTimeTypeTest dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b
+ // Affected by HHH-13266 (JDK-8061577)
+ .add( 1892, 1, 1, 0, 0, 0, 0, "GMT+00:00", ZONE_OSLO )
+ .add( 1892, 1, 1, 0, 0, 0, 0, "Europe/Oslo", ZONE_OSLO )
+ )
.skippedForDialects(
// MySQL/Mariadb/Sybase cannot store dates in 1600 in a timestamp.
- Arrays.asList( MySQLDialect.class, MariaDBDialect.class, SybaseDialect.class ),
+ dialect -> dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect || dialect instanceof SybaseDialect
+ || dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
b -> b
.add( 1600, 1, 1, 0, 0, 0, 0, "GMT+00:19:32", ZONE_AMSTERDAM )
.add( 1600, 1, 1, 0, 0, 0, 0, "Europe/Amsterdam", ZONE_AMSTERDAM )
)
// HHH-13379: DST end (where Timestamp becomes ambiguous, see JDK-4312621)
// => This used to work correctly in 5.4.1.Final and earlier
- .add( 2018, 10, 28, 2, 0, 0, 0, "+01:00", ZONE_PARIS )
- .add( 2018, 4, 1, 2, 0, 0, 0, "+12:00", ZONE_AUCKLAND )
+ .skippedForDialects(
+ dialect -> dialect instanceof H2Dialect && ( (H2Dialect) dialect ).hasDstBug(),
+ b -> b.add( 2018, 10, 28, 2, 0, 0, 0, "+01:00", ZONE_PARIS )
+ .add( 2018, 4, 1, 2, 0, 0, 0, "+12:00", ZONE_AUCKLAND )
+ )
// => This has never worked correctly, unless the JDBC timezone was set to UTC
.withForcedJdbcTimezone( "UTC", b -> b
.add( 2018, 10, 28, 2, 0, 0, 0, "+02:00", ZONE_PARIS )
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/typeoverride/TypeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/typeoverride/TypeOverrideTest.java
index caefdb3aa4..59c7b57dda 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/typeoverride/TypeOverrideTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/typeoverride/TypeOverrideTest.java
@@ -50,33 +50,34 @@ public class TypeOverrideTest extends BaseSessionFactoryFunctionalTest {
@Test
public void testStandardBasicSqlTypeDescriptor() {
+ final Dialect dialect = getMetadata().getDatabase().getDialect();
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = getMetadata().getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
// no override
assertSame( IntegerJdbcTypeDescriptor.INSTANCE, jdbcTypeRegistry.getDescriptor( Types.INTEGER ) );
// A few dialects explicitly override BlobTypeDescriptor.DEFAULT
- if ( CockroachDialect.class.isInstance( getDialect() ) ) {
+ if ( CockroachDialect.class.isInstance( dialect ) ) {
assertSame(
VarbinaryJdbcTypeDescriptor.INSTANCE,
jdbcTypeRegistry.getDescriptor( Types.BLOB )
);
}
- else if ( PostgreSQLDialect.class.isInstance( getDialect() ) ) {
+ else if ( PostgreSQLDialect.class.isInstance( dialect ) ) {
assertSame(
BlobJdbcTypeDescriptor.BLOB_BINDING,
jdbcTypeRegistry.getDescriptor( Types.BLOB )
);
}
- else if ( SybaseDialect.class.isInstance( getDialect() ) ) {
+ else if ( SybaseDialect.class.isInstance( dialect ) ) {
assertSame(
BlobJdbcTypeDescriptor.PRIMITIVE_ARRAY_BINDING,
jdbcTypeRegistry.getDescriptor( Types.BLOB )
);
}
- else if ( AbstractHANADialect.class.isInstance( getDialect() ) ) {
+ else if ( AbstractHANADialect.class.isInstance( dialect ) ) {
assertSame(
- ( (AbstractHANADialect) getDialect() ).getBlobTypeDescriptor(),
+ ( (AbstractHANADialect) dialect ).getBlobTypeDescriptor(),
jdbcTypeRegistry.getDescriptor( Types.BLOB )
);
}
diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java
index 8e90eec156..291c4f0ff7 100644
--- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java
@@ -17,6 +17,7 @@ import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
+import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.query.FetchClauseType;
/**
@@ -269,7 +270,7 @@ abstract public class DialectFeatureChecks {
public static class SupportsTimezoneTypes implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
- return dialect.supportsTimezoneTypes();
+ return dialect.getTimeZoneSupport() == TimeZoneSupport.NATIVE;
}
}