HHH-15820 make the default TimeZoneStorageStrategy for [Zoned|Offset]DateTime depend on the dialect
Define TimeZoneStorageType.DEFAULT, uses NATIVE if possible, falls back to NORMALIZE_UTC so that for dialects with proper support for TIMESTAMP WITH TIME ZONE we use it this is consistent with what we already do for Instant
This commit is contained in:
parent
a4f301814b
commit
863dda5cf5
|
@ -49,6 +49,15 @@ public enum TimeZoneStorageType {
|
||||||
* {@link org.hibernate.dialect.TimeZoneSupport#NATIVE},
|
* {@link org.hibernate.dialect.TimeZoneSupport#NATIVE},
|
||||||
* otherwise uses the {@link #COLUMN} strategy.
|
* otherwise uses the {@link #COLUMN} strategy.
|
||||||
*/
|
*/
|
||||||
AUTO
|
AUTO,
|
||||||
|
/**
|
||||||
|
* Stores the time zone either with {@link #NATIVE} if
|
||||||
|
* {@link Dialect#getTimeZoneSupport()} is
|
||||||
|
* {@link org.hibernate.dialect.TimeZoneSupport#NATIVE},
|
||||||
|
* otherwise uses the {@link #NORMALIZE_UTC} strategy.
|
||||||
|
*
|
||||||
|
* @since 6.2
|
||||||
|
*/
|
||||||
|
DEFAULT
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
import org.hibernate.metamodel.CollectionClassification;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.service.spi.ServiceException;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.usertype.UserType;
|
||||||
|
@ -538,7 +539,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
private final StandardServiceRegistry serviceRegistry;
|
private final StandardServiceRegistry serviceRegistry;
|
||||||
private final MappingDefaultsImpl mappingDefaults;
|
private final MappingDefaultsImpl mappingDefaults;
|
||||||
private final IdentifierGeneratorFactory identifierGeneratorFactory;
|
private final IdentifierGeneratorFactory identifierGeneratorFactory;
|
||||||
private final TimeZoneStorageStrategy defaultTimezoneStorage;
|
private final TimeZoneStorageType defaultTimezoneStorage;
|
||||||
|
|
||||||
// todo (6.0) : remove bootstrapContext property along with the deprecated methods
|
// todo (6.0) : remove bootstrapContext property along with the deprecated methods
|
||||||
private BootstrapContext bootstrapContext;
|
private BootstrapContext bootstrapContext;
|
||||||
|
@ -573,7 +574,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
|
|
||||||
this.mappingDefaults = new MappingDefaultsImpl( serviceRegistry );
|
this.mappingDefaults = new MappingDefaultsImpl( serviceRegistry );
|
||||||
|
|
||||||
this.defaultTimezoneStorage = resolveTimeZoneStorageStrategy( serviceRegistry, configService );
|
this.defaultTimezoneStorage = resolveTimeZoneStorageStrategy( configService );
|
||||||
this.multiTenancyEnabled = serviceRegistry.getService(MultiTenantConnectionProvider.class)!=null;
|
this.multiTenancyEnabled = serviceRegistry.getService(MultiTenantConnectionProvider.class)!=null;
|
||||||
|
|
||||||
this.xmlMappingEnabled = configService.getSetting(
|
this.xmlMappingEnabled = configService.getSetting(
|
||||||
|
@ -745,7 +746,55 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
|
public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
|
||||||
return defaultTimezoneStorage;
|
return toTimeZoneStorageStrategy( getTimeZoneSupport( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TimeZoneSupport getTimeZoneSupport(StandardServiceRegistry serviceRegistry) {
|
||||||
|
try {
|
||||||
|
return serviceRegistry.getService( JdbcServices.class )
|
||||||
|
.getDialect()
|
||||||
|
.getTimeZoneSupport();
|
||||||
|
}
|
||||||
|
catch (ServiceException se) {
|
||||||
|
return TimeZoneSupport.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private TimeZoneStorageStrategy toTimeZoneStorageStrategy(TimeZoneSupport timeZoneSupport) {
|
||||||
|
switch ( defaultTimezoneStorage ) {
|
||||||
|
case NATIVE:
|
||||||
|
if ( timeZoneSupport != TimeZoneSupport.NATIVE ) {
|
||||||
|
throw new HibernateException( "The configured time zone storage type NATIVE is not supported with the configured dialect" );
|
||||||
|
}
|
||||||
|
return TimeZoneStorageStrategy.NATIVE;
|
||||||
|
case COLUMN:
|
||||||
|
return TimeZoneStorageStrategy.COLUMN;
|
||||||
|
case NORMALIZE:
|
||||||
|
return TimeZoneStorageStrategy.NORMALIZE;
|
||||||
|
case NORMALIZE_UTC:
|
||||||
|
return TimeZoneStorageStrategy.NORMALIZE_UTC;
|
||||||
|
case AUTO:
|
||||||
|
switch (timeZoneSupport) {
|
||||||
|
case NATIVE:
|
||||||
|
return TimeZoneStorageStrategy.NATIVE;
|
||||||
|
case NORMALIZE:
|
||||||
|
case NONE:
|
||||||
|
return TimeZoneStorageStrategy.COLUMN;
|
||||||
|
default:
|
||||||
|
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
||||||
|
}
|
||||||
|
case DEFAULT:
|
||||||
|
switch (timeZoneSupport) {
|
||||||
|
case NATIVE:
|
||||||
|
return TimeZoneStorageStrategy.NATIVE;
|
||||||
|
case NORMALIZE:
|
||||||
|
case NONE:
|
||||||
|
return TimeZoneStorageStrategy.NORMALIZE_UTC;
|
||||||
|
default:
|
||||||
|
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new HibernateException( "Unsupported time zone storage type: " + defaultTimezoneStorage );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -861,56 +910,12 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeZoneStorageStrategy resolveTimeZoneStorageStrategy(
|
private static TimeZoneStorageType resolveTimeZoneStorageStrategy(
|
||||||
StandardServiceRegistry serviceRegistry,
|
|
||||||
ConfigurationService configService) {
|
ConfigurationService configService) {
|
||||||
final TimeZoneStorageType configuredTimeZoneStorageType = configService.getSetting(
|
return configService.getSetting(
|
||||||
AvailableSettings.TIMEZONE_DEFAULT_STORAGE,
|
AvailableSettings.TIMEZONE_DEFAULT_STORAGE,
|
||||||
value -> TimeZoneStorageType.valueOf( value.toString() ),
|
value -> TimeZoneStorageType.valueOf( value.toString() ),
|
||||||
null
|
TimeZoneStorageType.DEFAULT
|
||||||
);
|
);
|
||||||
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 NORMALIZE_UTC:
|
|
||||||
resolvedTimezoneStorage = TimeZoneStorageStrategy.NORMALIZE_UTC;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.TimeZoneStorageType;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.dialect.H2Dialect;
|
import org.hibernate.dialect.H2Dialect;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.dialect.MariaDBDialect;
|
import org.hibernate.dialect.MariaDBDialect;
|
||||||
|
@ -42,6 +45,12 @@ import static org.junit.Assert.assertThat;
|
||||||
@TestForIssue(jiraKey = "HHH-10372")
|
@TestForIssue(jiraKey = "HHH-10372")
|
||||||
public class OffsetDateTimeTest extends AbstractJavaTimeTypeTest<OffsetDateTime, OffsetDateTimeTest.EntityWithOffsetDateTime> {
|
public class OffsetDateTimeTest extends AbstractJavaTimeTypeTest<OffsetDateTime, OffsetDateTimeTest.EntityWithOffsetDateTime> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration configuration) {
|
||||||
|
super.configure(configuration);
|
||||||
|
configuration.setProperty( AvailableSettings.TIMEZONE_DEFAULT_STORAGE, TimeZoneStorageType.NORMALIZE.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
private static class ParametersBuilder extends AbstractParametersBuilder<ParametersBuilder> {
|
private static class ParametersBuilder extends AbstractParametersBuilder<ParametersBuilder> {
|
||||||
public ParametersBuilder add(int year, int month, int day,
|
public ParametersBuilder add(int year, int month, int day,
|
||||||
int hour, int minute, int second, int nanosecond, String offset, ZoneId defaultTimeZone) {
|
int hour, int minute, int second, int nanosecond, String offset, ZoneId defaultTimeZone) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.TimeZoneStorageType;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.dialect.H2Dialect;
|
import org.hibernate.dialect.H2Dialect;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.dialect.MariaDBDialect;
|
import org.hibernate.dialect.MariaDBDialect;
|
||||||
|
@ -42,6 +45,12 @@ import static org.junit.Assert.assertThat;
|
||||||
@TestForIssue(jiraKey = "HHH-10372")
|
@TestForIssue(jiraKey = "HHH-10372")
|
||||||
public class ZonedDateTimeTest extends AbstractJavaTimeTypeTest<ZonedDateTime, ZonedDateTimeTest.EntityWithZonedDateTime> {
|
public class ZonedDateTimeTest extends AbstractJavaTimeTypeTest<ZonedDateTime, ZonedDateTimeTest.EntityWithZonedDateTime> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(Configuration configuration) {
|
||||||
|
super.configure(configuration);
|
||||||
|
configuration.setProperty( AvailableSettings.TIMEZONE_DEFAULT_STORAGE, TimeZoneStorageType.NORMALIZE.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
private static class ParametersBuilder extends AbstractParametersBuilder<ParametersBuilder> {
|
private static class ParametersBuilder extends AbstractParametersBuilder<ParametersBuilder> {
|
||||||
public ParametersBuilder add(int year, int month, int day,
|
public ParametersBuilder add(int year, int month, int day,
|
||||||
int hour, int minute, int second, int nanosecond, String zone, ZoneId defaultTimeZone) {
|
int hour, int minute, int second, int nanosecond, String zone, ZoneId defaultTimeZone) {
|
||||||
|
|
Loading…
Reference in New Issue