Handle TimeZoneStorage annotation

This commit is contained in:
Christian Beikov 2021-10-11 10:43:32 +02:00
parent 548df627e6
commit ba350d13c6
3 changed files with 162 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import java.util.function.Function;
import jakarta.persistence.TemporalType;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.TimeZoneStorageType;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.mapping.JdbcMapping;
@ -37,6 +38,7 @@ public class VersionResolution<E> implements BasicValue.Resolution<E> {
Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess,
Function<TypeConfiguration, BasicJavaTypeDescriptor> explicitJtdAccess,
Function<TypeConfiguration, JdbcTypeDescriptor> explicitStdAccess,
TimeZoneStorageType timeZoneStorageType,
TypeConfiguration typeConfiguration,
@SuppressWarnings("unused") MetadataBuildingContext context) {
@ -61,6 +63,16 @@ public class VersionResolution<E> implements BasicValue.Resolution<E> {
@Override
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
if ( timeZoneStorageType != null ) {
switch ( timeZoneStorageType ) {
case COLUMN:
return TimeZoneStorageStrategy.COLUMN;
case NATIVE:
return TimeZoneStorageStrategy.NATIVE;
case NORMALIZE:
return TimeZoneStorageStrategy.NORMALIZE;
}
}
return context.getBuildingOptions().getDefaultTimeZoneStorage();
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.cfg.annotations;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collections;
@ -17,6 +18,7 @@ import java.util.function.Function;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.AnyDiscriminator;
import org.hibernate.annotations.AnyKeyJavaClass;
@ -46,6 +48,10 @@ import org.hibernate.annotations.Mutability;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.TimeZoneColumn;
import org.hibernate.annotations.TimeZoneStorage;
import org.hibernate.annotations.TimeZoneStorageType;
import org.hibernate.annotations.TimeZoneType;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.internal.NoJavaTypeDescriptor;
@ -64,6 +70,7 @@ import org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass;
import org.hibernate.cfg.SetBasicValueTypeSecondPass;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
@ -85,6 +92,7 @@ import org.hibernate.usertype.UserType;
import org.jboss.logging.Logger;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
@ -157,6 +165,7 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
private boolean isLob;
private EnumType enumType;
private TemporalType temporalPrecision;
private TimeZoneStorageType timeZoneStorageType;
private Table table;
private Ejb3Column[] columns;
@ -193,6 +202,16 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
}
@Override
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
if ( timeZoneStorageType != null ) {
switch ( timeZoneStorageType ) {
case COLUMN:
return TimeZoneStorageStrategy.COLUMN;
case NATIVE:
return TimeZoneStorageStrategy.NATIVE;
case NORMALIZE:
return TimeZoneStorageStrategy.NORMALIZE;
}
}
return buildingContext.getBuildingOptions().getDefaultTimeZoneStorage();
}
@ -680,6 +699,109 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
enumType = null;
}
final TimeZoneStorage timeZoneStorageAnn = attributeXProperty.getAnnotation( TimeZoneStorage.class );
if ( timeZoneStorageAnn != null ) {
timeZoneStorageType = timeZoneStorageAnn.value();
final TimeZoneColumn timeZoneColumnAnn = attributeXProperty.getAnnotation( TimeZoneColumn.class );
final Column column;
final TimeZoneType type;
if ( timeZoneColumnAnn != null ) {
column = timeZoneColumnAnn.column();
type = timeZoneColumnAnn.type();
}
else {
switch ( timeZoneStorageType ) {
case AUTO:
final Dialect dialect = buildingContext.getBootstrapContext().getServiceRegistry()
.getService( JdbcServices.class ).getDialect();
if ( dialect.getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
column = null;
type = null;
break;
}
case COLUMN:
final String timeZoneColumnName = columns[0].getName() + "_tz";
column = new Column() {
@Override
public String name() {
return timeZoneColumnName;
}
@Override
public boolean unique() {
return false;
}
@Override
public boolean nullable() {
return columns[0].isNullable();
}
@Override
public boolean insertable() {
return columns[0].isInsertable();
}
@Override
public boolean updatable() {
return columns[0].isUpdatable();
}
@Override
public String columnDefinition() {
return "";
}
@Override
public String table() {
return columns[0].getExplicitTableName();
}
@Override
public int length() {
return 255;
}
@Override
public int precision() {
return 0;
}
@Override
public int scale() {
return 0;
}
@Override
public Class<? extends Annotation> annotationType() {
return Column.class;
}
};
type = TimeZoneType.OFFSET;
break;
default:
column = null;
type = null;
break;
}
}
if ( column != null ) {
// todo (6.0): do something with the column
// maybe move this to AnnotationBinder#2266 and make it treat the property as composite for the COLUMN strategy
throw new NotYetImplementedFor6Exception("TimeZoneColumn support is not yet implemented!");
}
else if ( timeZoneColumnAnn != null ) {
throw new IllegalStateException(
"@TimeZoneColumn can not be used in conjunction with @TimeZoneStorage( " + timeZoneStorageType +
" ) with attribute " + attributeXProperty.getDeclaringClass().getName() +
'.' + attributeXProperty.getName()
);
}
}
else {
timeZoneStorageType = null;
}
normalSupplementalDetails( attributeXProperty, buildingContext );
// layer in support for JPA's approach for specifying a specific Java type for the collection elements...
@ -1123,6 +1245,10 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
basicValue.setEnumerationStyle( enumType );
}
if ( timeZoneStorageType != null ) {
basicValue.setTimeZoneStorageType( timeZoneStorageType );
}
if ( temporalPrecision != null ) {
basicValue.setTemporalPrecision( temporalPrecision );
}
@ -1219,6 +1345,10 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
basicValue.setEnumerationStyle( enumType );
}
if ( timeZoneStorageType != null ) {
basicValue.setTimeZoneStorageType( timeZoneStorageType );
}
if ( temporalPrecision != null ) {
basicValue.setTemporalPrecision( temporalPrecision );
}

View File

@ -13,6 +13,7 @@ import java.util.function.Function;
import org.hibernate.MappingException;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.TimeZoneStorageType;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.TypeDefinitionRegistry;
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
@ -83,6 +84,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
private EnumType enumerationStyle;
private TemporalType temporalPrecision;
private TimeZoneStorageType timeZoneStorageType;
private java.lang.reflect.Type resolvedJavaType;
@ -131,6 +133,13 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
return enumerationStyle;
}
public TimeZoneStorageType getTimeZoneStorageType() {
return timeZoneStorageType;
}
public void setTimeZoneStorageType(TimeZoneStorageType timeZoneStorageType) {
this.timeZoneStorageType = timeZoneStorageType;
}
public void setJpaAttributeConverterDescriptor(ConverterDescriptor descriptor) {
setAttributeConverterDescriptor( descriptor );
@ -316,6 +325,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
implicitJavaTypeAccess,
explicitJavaTypeAccess,
explicitJdbcTypeAccess,
timeZoneStorageType,
typeConfiguration,
getBuildingContext()
);
@ -604,6 +614,16 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
@Override
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
if ( timeZoneStorageType != null ) {
switch ( timeZoneStorageType ) {
case COLUMN:
return TimeZoneStorageStrategy.COLUMN;
case NATIVE:
return TimeZoneStorageStrategy.NATIVE;
case NORMALIZE:
return TimeZoneStorageStrategy.NORMALIZE;
}
}
return getBuildingContext().getBuildingOptions().getDefaultTimeZoneStorage();
}