HHH-15828 fix setting TIMEZONE_DEFAULT_STORAGE to COLUMN
This commit is contained in:
parent
4fba6ac60d
commit
ee66a93302
|
@ -746,10 +746,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
|
public TimeZoneStorageStrategy getDefaultTimeZoneStorage() {
|
||||||
return toTimeZoneStorageStrategy( getTimeZoneSupport( serviceRegistry ) );
|
return toTimeZoneStorageStrategy( getTimeZoneSupport() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeZoneSupport getTimeZoneSupport(StandardServiceRegistry serviceRegistry) {
|
@Override
|
||||||
|
public TimeZoneSupport getTimeZoneSupport() {
|
||||||
try {
|
try {
|
||||||
return serviceRegistry.getService( JdbcServices.class )
|
return serviceRegistry.getService( JdbcServices.class )
|
||||||
.getDialect()
|
.getDialect()
|
||||||
|
@ -759,6 +760,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
return TimeZoneSupport.NONE;
|
return TimeZoneSupport.NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeZoneStorageStrategy toTimeZoneStorageStrategy(TimeZoneSupport timeZoneSupport) {
|
private TimeZoneStorageStrategy toTimeZoneStorageStrategy(TimeZoneSupport timeZoneSupport) {
|
||||||
switch ( defaultTimezoneStorage ) {
|
switch ( defaultTimezoneStorage ) {
|
||||||
case NATIVE:
|
case NATIVE:
|
||||||
|
@ -775,9 +777,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
case AUTO:
|
case AUTO:
|
||||||
switch (timeZoneSupport) {
|
switch (timeZoneSupport) {
|
||||||
case NATIVE:
|
case NATIVE:
|
||||||
|
// if the db has native support for timezones, we use that, not a column
|
||||||
return TimeZoneStorageStrategy.NATIVE;
|
return TimeZoneStorageStrategy.NATIVE;
|
||||||
case NORMALIZE:
|
case NORMALIZE:
|
||||||
case NONE:
|
case NONE:
|
||||||
|
// otherwise we use a separate column
|
||||||
return TimeZoneStorageStrategy.COLUMN;
|
return TimeZoneStorageStrategy.COLUMN;
|
||||||
default:
|
default:
|
||||||
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
||||||
|
@ -785,9 +789,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
case DEFAULT:
|
case DEFAULT:
|
||||||
switch (timeZoneSupport) {
|
switch (timeZoneSupport) {
|
||||||
case NATIVE:
|
case NATIVE:
|
||||||
|
// if the db has native support for timezones, we use that, and don't normalize
|
||||||
return TimeZoneStorageStrategy.NATIVE;
|
return TimeZoneStorageStrategy.NATIVE;
|
||||||
case NORMALIZE:
|
case NORMALIZE:
|
||||||
case NONE:
|
case NONE:
|
||||||
|
// otherwise we normalize things to UTC
|
||||||
return TimeZoneStorageStrategy.NORMALIZE_UTC;
|
return TimeZoneStorageStrategy.NORMALIZE_UTC;
|
||||||
default:
|
default:
|
||||||
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
throw new HibernateException( "Unsupported time zone support: " + timeZoneSupport);
|
||||||
|
|
|
@ -66,7 +66,7 @@ import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferre
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForUuid;
|
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForUuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the process of of transforming a {@link MetadataSources}
|
* Represents the process of transforming a {@link MetadataSources}
|
||||||
* reference into a {@link org.hibernate.boot.Metadata} reference. Allows for 2 different process paradigms:<ul>
|
* reference into a {@link org.hibernate.boot.Metadata} reference. Allows for 2 different process paradigms:<ul>
|
||||||
* <li>
|
* <li>
|
||||||
* Single step : as defined by the {@link #build} method; internally leverages the 2-step paradigm
|
* Single step : as defined by the {@link #build} method; internally leverages the 2-step paradigm
|
||||||
|
@ -465,7 +465,7 @@ public class MetadataBuildingProcess {
|
||||||
if ( timestampWithTimeZoneOverride != null ) {
|
if ( timestampWithTimeZoneOverride != null ) {
|
||||||
adaptToDefaultTimeZoneStorage( typeConfiguration, timestampWithTimeZoneOverride );
|
adaptToDefaultTimeZoneStorage( typeConfiguration, timestampWithTimeZoneOverride );
|
||||||
}
|
}
|
||||||
final int preferredSqlTypeCodeForInstant = getPreferredSqlTypeCodeForInstant(serviceRegistry);
|
final int preferredSqlTypeCodeForInstant = getPreferredSqlTypeCodeForInstant( serviceRegistry );
|
||||||
if ( preferredSqlTypeCodeForInstant != SqlTypes.TIMESTAMP_UTC ) {
|
if ( preferredSqlTypeCodeForInstant != SqlTypes.TIMESTAMP_UTC ) {
|
||||||
adaptToPreferredSqlTypeCodeForInstant( typeConfiguration, jdbcTypeRegistry, preferredSqlTypeCodeForInstant );
|
adaptToPreferredSqlTypeCodeForInstant( typeConfiguration, jdbcTypeRegistry, preferredSqlTypeCodeForInstant );
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.cache.spi.access.AccessType;
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.cfg.MetadataSourceType;
|
import org.hibernate.cfg.MetadataSourceType;
|
||||||
|
import org.hibernate.dialect.TimeZoneSupport;
|
||||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
@ -58,6 +59,11 @@ public abstract class AbstractDelegatingMetadataBuildingOptions implements Metad
|
||||||
return delegate.getDefaultTimeZoneStorage();
|
return delegate.getDefaultTimeZoneStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZoneSupport getTimeZoneSupport() {
|
||||||
|
return delegate.getTimeZoneSupport();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BasicTypeRegistration> getBasicTypeRegistrations() {
|
public List<BasicTypeRegistration> getBasicTypeRegistrations() {
|
||||||
return delegate.getBasicTypeRegistrations();
|
return delegate.getBasicTypeRegistrations();
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.cfg.MetadataSourceType;
|
import org.hibernate.cfg.MetadataSourceType;
|
||||||
import org.hibernate.collection.internal.StandardCollectionSemanticsResolver;
|
import org.hibernate.collection.internal.StandardCollectionSemanticsResolver;
|
||||||
import org.hibernate.collection.spi.CollectionSemanticsResolver;
|
import org.hibernate.collection.spi.CollectionSemanticsResolver;
|
||||||
|
import org.hibernate.dialect.TimeZoneSupport;
|
||||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||||
import org.hibernate.metamodel.internal.ManagedTypeRepresentationResolverStandard;
|
import org.hibernate.metamodel.internal.ManagedTypeRepresentationResolverStandard;
|
||||||
import org.hibernate.metamodel.spi.ManagedTypeRepresentationResolver;
|
import org.hibernate.metamodel.spi.ManagedTypeRepresentationResolver;
|
||||||
|
@ -51,6 +52,8 @@ public interface MetadataBuildingOptions {
|
||||||
|
|
||||||
TimeZoneStorageStrategy getDefaultTimeZoneStorage();
|
TimeZoneStorageStrategy getDefaultTimeZoneStorage();
|
||||||
|
|
||||||
|
TimeZoneSupport getTimeZoneSupport();
|
||||||
|
|
||||||
default ManagedTypeRepresentationResolver getManagedTypeRepresentationResolver() {
|
default ManagedTypeRepresentationResolver getManagedTypeRepresentationResolver() {
|
||||||
// for now always return the standard one
|
// for now always return the standard one
|
||||||
return ManagedTypeRepresentationResolverStandard.INSTANCE;
|
return ManagedTypeRepresentationResolverStandard.INSTANCE;
|
||||||
|
|
|
@ -26,12 +26,9 @@ import jakarta.persistence.MappedSuperclass;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.Internal;
|
|
||||||
import org.hibernate.TimeZoneStorageStrategy;
|
|
||||||
import org.hibernate.annotations.ColumnTransformer;
|
import org.hibernate.annotations.ColumnTransformer;
|
||||||
import org.hibernate.annotations.ColumnTransformers;
|
import org.hibernate.annotations.ColumnTransformers;
|
||||||
import org.hibernate.annotations.TimeZoneColumn;
|
import org.hibernate.annotations.TimeZoneColumn;
|
||||||
import org.hibernate.annotations.TimeZoneStorage;
|
|
||||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
|
@ -47,6 +44,8 @@ import org.hibernate.usertype.internal.AbstractTimeZoneStorageCompositeUserType;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.AnnotationBinder.useColumnForTimeZoneStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
|
@ -64,8 +63,8 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
||||||
private Map<String, JoinTable> currentPropertyJoinTableOverride;
|
private Map<String, JoinTable> currentPropertyJoinTableOverride;
|
||||||
private Map<String, ForeignKey> holderForeignKeyOverride;
|
private Map<String, ForeignKey> holderForeignKeyOverride;
|
||||||
private Map<String, ForeignKey> currentPropertyForeignKeyOverride;
|
private Map<String, ForeignKey> currentPropertyForeignKeyOverride;
|
||||||
private String path;
|
private final String path;
|
||||||
private MetadataBuildingContext context;
|
private final MetadataBuildingContext context;
|
||||||
private Boolean isInIdClass;
|
private Boolean isInIdClass;
|
||||||
|
|
||||||
AbstractPropertyHolder(
|
AbstractPropertyHolder(
|
||||||
|
@ -192,7 +191,7 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
||||||
this.currentPropertyColumnOverride = null;
|
this.currentPropertyColumnOverride = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentPropertyColumnTransformerOverride = buildColumnTransformerOverride( property, getPath() );
|
this.currentPropertyColumnTransformerOverride = buildColumnTransformerOverride( property );
|
||||||
if ( this.currentPropertyColumnTransformerOverride.size() == 0 ) {
|
if ( this.currentPropertyColumnTransformerOverride.size() == 0 ) {
|
||||||
this.currentPropertyColumnTransformerOverride = null;
|
this.currentPropertyColumnTransformerOverride = null;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +216,7 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
||||||
/**
|
/**
|
||||||
* Get column overriding, property first, then parent, then holder
|
* Get column overriding, property first, then parent, then holder
|
||||||
* replace the placeholder 'collection&&element' with nothing
|
* replace the placeholder 'collection&&element' with nothing
|
||||||
*
|
* <p>
|
||||||
* These rules are here to support both JPA 2 and legacy overriding rules.
|
* These rules are here to support both JPA 2 and legacy overriding rules.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -416,7 +415,7 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
||||||
|| current.isAnnotationPresent( Embeddable.class ) ) {
|
|| current.isAnnotationPresent( Embeddable.class ) ) {
|
||||||
//FIXME is embeddable override?
|
//FIXME is embeddable override?
|
||||||
Map<String, Column[]> currentOverride = buildColumnOverride( current, getPath(), context );
|
Map<String, Column[]> currentOverride = buildColumnOverride( current, getPath(), context );
|
||||||
Map<String, ColumnTransformer> currentTransformerOverride = buildColumnTransformerOverride( current, getPath() );
|
Map<String, ColumnTransformer> currentTransformerOverride = buildColumnTransformerOverride( current );
|
||||||
Map<String, JoinColumn[]> currentJoinOverride = buildJoinColumnOverride( current, getPath() );
|
Map<String, JoinColumn[]> currentJoinOverride = buildJoinColumnOverride( current, getPath() );
|
||||||
Map<String, JoinTable> currentJoinTableOverride = buildJoinTableOverride( current, getPath() );
|
Map<String, JoinTable> currentJoinTableOverride = buildJoinTableOverride( current, getPath() );
|
||||||
Map<String, ForeignKey> currentForeignKeyOverride = buildForeignKeyOverride( current, getPath() );
|
Map<String, ForeignKey> currentForeignKeyOverride = buildForeignKeyOverride( current, getPath() );
|
||||||
|
@ -477,105 +476,97 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, List<Column>> entry : columnOverrideList.entrySet()) {
|
for ( Map.Entry<String, List<Column>> entry : columnOverrideList.entrySet() ) {
|
||||||
columnOverride.put(
|
columnOverride.put( entry.getKey(), entry.getValue().toArray( new Column[0] ) );
|
||||||
entry.getKey(),
|
|
||||||
entry.getValue().toArray( new Column[entry.getValue().size()] )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if ( useColumnForTimeZoneStorage( element, context ) ) {
|
||||||
final TimeZoneStorage timeZoneStorage = element.getAnnotation( TimeZoneStorage.class );
|
final Column column = createTimestampColumn( element, path, context );
|
||||||
if ( timeZoneStorage != null ) {
|
columnOverride.put(
|
||||||
switch ( timeZoneStorage.value() ) {
|
path + "." + AbstractTimeZoneStorageCompositeUserType.INSTANT_NAME,
|
||||||
case AUTO:
|
new Column[]{ column }
|
||||||
if ( context.getBuildingOptions().getDefaultTimeZoneStorage() != TimeZoneStorageStrategy.COLUMN ) {
|
);
|
||||||
break;
|
final Column offsetColumn = createTimeZoneColumn( element, column );
|
||||||
}
|
columnOverride.put(
|
||||||
case COLUMN:
|
path + "." + AbstractTimeZoneStorageCompositeUserType.ZONE_OFFSET_NAME,
|
||||||
final Column column;
|
new Column[]{ offsetColumn }
|
||||||
final Column annotatedColumn = element.getAnnotation( Column.class );
|
);
|
||||||
if ( annotatedColumn != null ) {
|
|
||||||
column = annotatedColumn;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Base the name of the synthetic dateTime field on the name of the original attribute
|
|
||||||
final Identifier implicitName = context.getObjectNameNormalizer().normalizeIdentifierQuoting(
|
|
||||||
context.getBuildingOptions().getImplicitNamingStrategy().determineBasicColumnName(
|
|
||||||
new ImplicitBasicColumnNameSource() {
|
|
||||||
final AttributePath attributePath = AttributePath.parse( path );
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AttributePath getAttributePath() {
|
|
||||||
return attributePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCollectionElement() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataBuildingContext getBuildingContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
column = new ColumnImpl(
|
|
||||||
implicitName.getText(),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
columnOverride.put(
|
|
||||||
path + "." + AbstractTimeZoneStorageCompositeUserType.INSTANT_NAME,
|
|
||||||
new Column[] { column }
|
|
||||||
);
|
|
||||||
final Column offsetColumn;
|
|
||||||
final TimeZoneColumn timeZoneColumn = element.getAnnotation( TimeZoneColumn.class );
|
|
||||||
if ( timeZoneColumn != null ) {
|
|
||||||
offsetColumn = new ColumnImpl(
|
|
||||||
timeZoneColumn.name(),
|
|
||||||
false,
|
|
||||||
column.nullable(),
|
|
||||||
timeZoneColumn.insertable(),
|
|
||||||
timeZoneColumn.updatable(),
|
|
||||||
timeZoneColumn.columnDefinition(),
|
|
||||||
timeZoneColumn.table(),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
offsetColumn = new ColumnImpl(
|
|
||||||
column.name() + "_tz",
|
|
||||||
false,
|
|
||||||
column.nullable(),
|
|
||||||
column.insertable(),
|
|
||||||
column.updatable(),
|
|
||||||
"",
|
|
||||||
column.table(),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
columnOverride.put(
|
|
||||||
path + "." + AbstractTimeZoneStorageCompositeUserType.ZONE_OFFSET_NAME,
|
|
||||||
new Column[] { offsetColumn }
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return columnOverride;
|
return columnOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, ColumnTransformer> buildColumnTransformerOverride(XAnnotatedElement element, String path) {
|
private static Column createTimeZoneColumn(XAnnotatedElement element, Column column) {
|
||||||
|
final TimeZoneColumn timeZoneColumn = element.getAnnotation( TimeZoneColumn.class );
|
||||||
|
if ( timeZoneColumn != null ) {
|
||||||
|
return new ColumnImpl(
|
||||||
|
timeZoneColumn.name(),
|
||||||
|
false,
|
||||||
|
column.nullable(),
|
||||||
|
timeZoneColumn.insertable(),
|
||||||
|
timeZoneColumn.updatable(),
|
||||||
|
timeZoneColumn.columnDefinition(),
|
||||||
|
timeZoneColumn.table(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new ColumnImpl(
|
||||||
|
column.name() + "_tz",
|
||||||
|
false,
|
||||||
|
column.nullable(),
|
||||||
|
column.insertable(),
|
||||||
|
column.updatable(),
|
||||||
|
"",
|
||||||
|
column.table(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Column createTimestampColumn(XAnnotatedElement element, String path, MetadataBuildingContext context) {
|
||||||
|
final Column annotatedColumn = element.getAnnotation( Column.class );
|
||||||
|
if ( annotatedColumn != null ) {
|
||||||
|
return annotatedColumn;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Base the name of the synthetic dateTime field on the name of the original attribute
|
||||||
|
final Identifier implicitName = context.getObjectNameNormalizer().normalizeIdentifierQuoting(
|
||||||
|
context.getBuildingOptions().getImplicitNamingStrategy().determineBasicColumnName(
|
||||||
|
new ImplicitBasicColumnNameSource() {
|
||||||
|
final AttributePath attributePath = AttributePath.parse(path);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributePath getAttributePath() {
|
||||||
|
return attributePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCollectionElement() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetadataBuildingContext getBuildingContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return new ColumnImpl(
|
||||||
|
implicitName.getText(),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, ColumnTransformer> buildColumnTransformerOverride(XAnnotatedElement element) {
|
||||||
Map<String, ColumnTransformer> columnOverride = new HashMap<>();
|
Map<String, ColumnTransformer> columnOverride = new HashMap<>();
|
||||||
if ( element != null ) {
|
if ( element != null ) {
|
||||||
ColumnTransformer singleOverride = element.getAnnotation( ColumnTransformer.class );
|
ColumnTransformer singleOverride = element.getAnnotation( ColumnTransformer.class );
|
||||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.cfg;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -74,6 +76,7 @@ import org.hibernate.cfg.annotations.EntityBinder;
|
||||||
import org.hibernate.cfg.annotations.Nullability;
|
import org.hibernate.cfg.annotations.Nullability;
|
||||||
import org.hibernate.cfg.annotations.PropertyBinder;
|
import org.hibernate.cfg.annotations.PropertyBinder;
|
||||||
import org.hibernate.cfg.annotations.QueryBinder;
|
import org.hibernate.cfg.annotations.QueryBinder;
|
||||||
|
import org.hibernate.dialect.TimeZoneSupport;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
@ -171,6 +174,9 @@ import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
||||||
public final class AnnotationBinder {
|
public final class AnnotationBinder {
|
||||||
private static final CoreMessageLogger LOG = messageLogger( AnnotationBinder.class );
|
private static final CoreMessageLogger LOG = messageLogger( AnnotationBinder.class );
|
||||||
|
|
||||||
|
private static final String OFFSET_DATETIME_CLASS = OffsetDateTime.class.getName();
|
||||||
|
private static final String ZONED_DATETIME_CLASS = ZonedDateTime.class.getName();
|
||||||
|
|
||||||
private AnnotationBinder() {}
|
private AnnotationBinder() {}
|
||||||
|
|
||||||
public static void bindDefaults(MetadataBuildingContext context) {
|
public static void bindDefaults(MetadataBuildingContext context) {
|
||||||
|
@ -1780,31 +1786,6 @@ public final class AnnotationBinder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Class<? extends CompositeUserType<?>> resolveTimeZoneStorageCompositeUserType(
|
|
||||||
XProperty property,
|
|
||||||
XClass returnedClass,
|
|
||||||
MetadataBuildingContext context) {
|
|
||||||
if ( property != null ) {
|
|
||||||
final TimeZoneStorage timeZoneStorage = property.getAnnotation( TimeZoneStorage.class );
|
|
||||||
if ( timeZoneStorage != null ) {
|
|
||||||
switch ( timeZoneStorage.value() ) {
|
|
||||||
case AUTO:
|
|
||||||
if ( context.getBuildingOptions().getDefaultTimeZoneStorage() != TimeZoneStorageStrategy.COLUMN ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
case COLUMN:
|
|
||||||
switch ( returnedClass.getName() ) {
|
|
||||||
case "java.time.OffsetDateTime":
|
|
||||||
return OffsetDateTimeCompositeUserType.class;
|
|
||||||
case "java.time.ZonedDateTime":
|
|
||||||
return ZonedDateTimeCompositeUserType.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isGlobalGeneratorNameGlobal(MetadataBuildingContext context) {
|
private static boolean isGlobalGeneratorNameGlobal(MetadataBuildingContext context) {
|
||||||
return context.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled();
|
return context.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled();
|
||||||
}
|
}
|
||||||
|
@ -2495,4 +2476,51 @@ public final class AnnotationBinder {
|
||||||
LOG.ignoreNotFoundWithFetchTypeLazy( entity, association );
|
LOG.ignoreNotFoundWithFetchTypeLazy( entity, association );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Class<? extends CompositeUserType<?>> resolveTimeZoneStorageCompositeUserType(
|
||||||
|
XProperty property,
|
||||||
|
XClass returnedClass,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
if ( useColumnForTimeZoneStorage( property, context ) ) {
|
||||||
|
String returnedClassName = returnedClass.getName();
|
||||||
|
if ( OFFSET_DATETIME_CLASS.equals( returnedClassName ) ) {
|
||||||
|
return OffsetDateTimeCompositeUserType.class;
|
||||||
|
}
|
||||||
|
else if ( ZONED_DATETIME_CLASS.equals( returnedClassName ) ) {
|
||||||
|
return ZonedDateTimeCompositeUserType.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isZonedDateTimeClass(String returnedClassName) {
|
||||||
|
return OFFSET_DATETIME_CLASS.equals( returnedClassName )
|
||||||
|
|| ZONED_DATETIME_CLASS.equals( returnedClassName );
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean useColumnForTimeZoneStorage(XAnnotatedElement element, MetadataBuildingContext context) {
|
||||||
|
final TimeZoneStorage timeZoneStorage = element.getAnnotation( TimeZoneStorage.class );
|
||||||
|
if ( timeZoneStorage == null ) {
|
||||||
|
if ( element instanceof XProperty ) {
|
||||||
|
XProperty property = (XProperty) element;
|
||||||
|
return isZonedDateTimeClass( property.getType().getName() )
|
||||||
|
//no @TimeZoneStorage annotation, so we need to use the default storage strategy
|
||||||
|
&& context.getBuildingOptions().getDefaultTimeZoneStorage() == TimeZoneStorageStrategy.COLUMN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ( timeZoneStorage.value() ) {
|
||||||
|
case COLUMN:
|
||||||
|
return true;
|
||||||
|
case AUTO:
|
||||||
|
// if the db has native support for timezones, we use that, not a column
|
||||||
|
return context.getBuildingOptions().getTimeZoneSupport() != TimeZoneSupport.NATIVE;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -930,9 +930,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
|
|
||||||
final Target targetAnn = findAnnotation( attributeXProperty, Target.class );
|
final Target targetAnn = findAnnotation( attributeXProperty, Target.class );
|
||||||
if ( targetAnn != null ) {
|
if ( targetAnn != null ) {
|
||||||
return (BasicJavaType<?>) typeConfiguration
|
return (BasicJavaType<?>) typeConfiguration.getJavaTypeRegistry().getDescriptor( targetAnn.value() );
|
||||||
.getJavaTypeRegistry()
|
|
||||||
.getDescriptor( targetAnn.value() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -965,9 +963,6 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
timeZoneStorageType = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Class<? extends UserType<?>> normalizeUserType(Class<? extends UserType<?>> userType) {
|
private static Class<? extends UserType<?>> normalizeUserType(Class<? extends UserType<?>> userType) {
|
||||||
|
|
|
@ -13,7 +13,6 @@ import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
|
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
|
|
Loading…
Reference in New Issue