HHH-16125 complete redesign of how enum mappings work
- introduce SqlTypes.ENUM - no more converters! - finish of Potgres enum support - disable BIND for enums in Criteria on PostgreSQL (PostgreSQL doesn't do the needed type conversion to the enum type)
This commit is contained in:
parent
d348ae2d8c
commit
febf39cc55
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.model.process.internal;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.NativeEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.ObjectJavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.descriptor.jdbc.NativeEnumJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.internal.ConvertedBasicTypeImpl;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.EnumType;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.CHAR;
|
||||
import static org.hibernate.type.SqlTypes.VARCHAR;
|
||||
import static org.hibernate.type.SqlTypes.isCharacterType;
|
||||
|
||||
/**
|
||||
* Resolution for {@linkplain Enum enum} mappings using {@link jakarta.persistence.Enumerated},
|
||||
* either implicitly or explicitly
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EnumeratedValueResolution<E extends Enum<E>,R> implements BasicValue.Resolution<E> {
|
||||
public static final String PREFIX = "enum::";
|
||||
|
||||
private final EnumValueConverter<E,R> valueConverter;
|
||||
private final ConvertedBasicType<E> jdbcMapping;
|
||||
|
||||
public EnumeratedValueResolution(
|
||||
JdbcType jdbcType,
|
||||
EnumValueConverter<E, R> valueConverter) {
|
||||
this.valueConverter = valueConverter;
|
||||
|
||||
final String externalizableName = createName( valueConverter );
|
||||
this.jdbcMapping = new ConvertedBasicTypeImpl<>( externalizableName, jdbcType, valueConverter );
|
||||
|
||||
// todo (enum) : register database objects if needed
|
||||
}
|
||||
|
||||
private String createName(EnumValueConverter<E, R> valueConverter) {
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
PREFIX + "%s::%s",
|
||||
valueConverter.getDomainJavaType().getJavaType().getName(),
|
||||
enumStyle( valueConverter ).name()
|
||||
);
|
||||
}
|
||||
|
||||
private static EnumType enumStyle(EnumValueConverter<?,?> valueConverter) {
|
||||
if ( valueConverter instanceof NamedEnumValueConverter
|
||||
|| valueConverter instanceof NativeEnumValueConverter ) {
|
||||
return EnumType.STRING;
|
||||
}
|
||||
else if ( valueConverter instanceof OrdinalEnumValueConverter ) {
|
||||
return EnumType.ORDINAL;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConvertedBasicType<E> getJdbcMapping() {
|
||||
return jdbcMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConvertedBasicType<E> getLegacyResolvedBasicType() {
|
||||
return jdbcMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<E> getDomainJavaType() {
|
||||
return jdbcMapping.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<?> getRelationalJavaType() {
|
||||
return jdbcMapping.getJdbcJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcType getJdbcType() {
|
||||
return jdbcMapping.getJdbcType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumValueConverter<E,R> getValueConverter() {
|
||||
return valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan<E> getMutabilityPlan() {
|
||||
return ImmutableMutabilityPlan.instance();
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> EnumeratedValueResolution<E,?> fromName(
|
||||
String name,
|
||||
JdbcTypeIndicators jdbcTypeIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
assert name != null;
|
||||
assert name.startsWith( PREFIX );
|
||||
|
||||
final String[] parts = StringHelper.split( "::", name );
|
||||
assert parts.length == 3;
|
||||
assert "enum".equals( parts[0] );
|
||||
|
||||
final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration();
|
||||
final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry();
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
|
||||
|
||||
final Class<E> enumClass = resolveEnumClass( parts[1], context.getBootstrapContext() );
|
||||
final jakarta.persistence.EnumType style = jakarta.persistence.EnumType.valueOf( parts[ 2 ] );
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
final EnumJavaType<E> enumJavaType = (EnumJavaType) javaTypeRegistry.getDescriptor( enumClass );
|
||||
final JdbcType jdbcType = enumJavaType.getRecommendedJdbcType( jdbcTypeIndicators );
|
||||
final EnumValueConverter<E,?> converter;
|
||||
|
||||
switch ( style ) {
|
||||
case ORDINAL:
|
||||
final JavaType<Integer> integerJavaType = jdbcType.getJdbcRecommendedJavaTypeMapping(
|
||||
jdbcTypeIndicators.getColumnPrecision(),
|
||||
jdbcTypeIndicators.getColumnScale(),
|
||||
typeConfiguration
|
||||
);
|
||||
converter = new OrdinalEnumValueConverter<>( enumJavaType, jdbcType, integerJavaType );
|
||||
break;
|
||||
case STRING:
|
||||
if (jdbcType instanceof NativeEnumJdbcType) {
|
||||
converter = new NativeEnumValueConverter<>( enumJavaType, jdbcType, new ObjectJavaType() {
|
||||
@Override
|
||||
public <X> X unwrap(Object value, Class<X> type, WrapperOptions options) {
|
||||
if ( String.class.equals(type) && value instanceof Enum) {
|
||||
return (X) ((Enum<?>) value).name();
|
||||
}
|
||||
else {
|
||||
return super.unwrap(value, type, options);
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
else {
|
||||
final JavaType<String> stringJavaType = jdbcType.getJdbcRecommendedJavaTypeMapping(
|
||||
jdbcTypeIndicators.getColumnPrecision(),
|
||||
jdbcTypeIndicators.getColumnScale(),
|
||||
typeConfiguration
|
||||
);
|
||||
converter = new NamedEnumValueConverter<>( enumJavaType, jdbcType, stringJavaType );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( );
|
||||
}
|
||||
|
||||
return new EnumeratedValueResolution<>( jdbcType, converter );
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> Class<E> resolveEnumClass(String enumClassName, BootstrapContext bootstrapContext) {
|
||||
final ServiceRegistry serviceRegistry = bootstrapContext.getServiceRegistry();
|
||||
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
|
||||
return classLoaderService.classForName( enumClassName );
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import java.util.function.Function;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
|
@ -23,32 +24,23 @@ import org.hibernate.type.AdjustableBasicType;
|
|||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.SerializableType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.NativeEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeHelper;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.ObjectJavaType;
|
||||
import org.hibernate.type.descriptor.java.SerializableJavaType;
|
||||
import org.hibernate.type.descriptor.java.TemporalJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.descriptor.jdbc.NativeEnumJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
||||
import org.hibernate.type.internal.BasicTypeImpl;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.SMALLINT;
|
||||
import static org.hibernate.type.SqlTypes.TINYINT;
|
||||
import static org.hibernate.type.SqlTypes.isCharacterType;
|
||||
import static org.hibernate.type.descriptor.java.JavaTypeHelper.isTemporal;
|
||||
|
||||
/**
|
||||
* BasicValue.Resolution resolver for cases where no explicit
|
||||
|
@ -69,7 +61,8 @@ public class InferredBasicValueResolver {
|
|||
String propertyName,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
final Dialect dialect = buildingContext.getMetadataCollector().getDatabase().getDialect();
|
||||
final TypeConfiguration typeConfiguration = buildingContext.getBootstrapContext().getTypeConfiguration();
|
||||
final BootstrapContext bootstrapContext = buildingContext.getBootstrapContext();
|
||||
final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration();
|
||||
|
||||
final JavaType<T> reflectedJtd = reflectedJtdResolver.get();
|
||||
|
||||
|
@ -81,29 +74,17 @@ public class InferredBasicValueResolver {
|
|||
|
||||
if (explicitJavaType != null) {
|
||||
// we have an explicit JavaType
|
||||
if ( explicitJavaType instanceof EnumJavaType ) {
|
||||
return fromEnum(
|
||||
(EnumJavaType) explicitJavaType,
|
||||
null,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
buildingContext
|
||||
);
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( explicitJavaType ) ) {
|
||||
if ( isTemporal( explicitJavaType ) ) {
|
||||
return fromTemporal(
|
||||
(TemporalJavaType<T>) explicitJavaType,
|
||||
null,
|
||||
explicitJdbcType,
|
||||
resolvedJavaType,
|
||||
explicitMutabilityPlanAccess,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
stdIndicators
|
||||
);
|
||||
}
|
||||
else if ( explicitJdbcType != null ) {
|
||||
// we also have an explicit JdbcType
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
explicitJavaType,
|
||||
explicitJdbcType
|
||||
|
@ -132,30 +113,25 @@ public class InferredBasicValueResolver {
|
|||
else if ( reflectedJtd != null ) {
|
||||
// we were able to determine the "reflected java-type"
|
||||
// Use JTD if we know it to apply any specialized resolutions
|
||||
|
||||
if ( reflectedJtd instanceof EnumJavaType ) {
|
||||
return fromEnum(
|
||||
(EnumJavaType) reflectedJtd,
|
||||
null,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
buildingContext
|
||||
bootstrapContext
|
||||
);
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( reflectedJtd ) ) {
|
||||
else if ( isTemporal( reflectedJtd ) ) {
|
||||
return fromTemporal(
|
||||
(TemporalJavaType<T>) reflectedJtd,
|
||||
null,
|
||||
explicitJdbcType,
|
||||
resolvedJavaType,
|
||||
explicitMutabilityPlanAccess,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
stdIndicators
|
||||
);
|
||||
}
|
||||
else if ( explicitJdbcType != null ) {
|
||||
// we also have an explicit JdbcType
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
reflectedJtd,
|
||||
explicitJdbcType
|
||||
|
@ -170,24 +146,20 @@ public class InferredBasicValueResolver {
|
|||
final JavaType<?> elementJtd = containerJtd.getElementJavaType();
|
||||
final BasicType registeredElementType;
|
||||
if ( elementJtd instanceof EnumJavaType ) {
|
||||
final EnumeratedValueResolution<?,?> resolution = fromEnum(
|
||||
final BasicValue.Resolution<?> resolution = fromEnum(
|
||||
(EnumJavaType<?>) elementJtd,
|
||||
null,
|
||||
null,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
buildingContext
|
||||
);
|
||||
registeredElementType = resolution.getJdbcMapping();
|
||||
bootstrapContext);
|
||||
registeredElementType = (BasicType<?>) resolution.getJdbcMapping();
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( elementJtd ) ) {
|
||||
final InferredBasicValueResolution resolution = InferredBasicValueResolver.fromTemporal(
|
||||
(TemporalJavaType<T>) elementJtd,
|
||||
else if ( isTemporal( elementJtd ) ) {
|
||||
final BasicValue.Resolution<?> resolution = fromTemporal(
|
||||
(TemporalJavaType<?>) elementJtd,
|
||||
null,
|
||||
null,
|
||||
resolvedJavaType,
|
||||
explicitMutabilityPlanAccess,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
stdIndicators
|
||||
);
|
||||
registeredElementType = resolution.getLegacyResolvedBasicType();
|
||||
}
|
||||
|
@ -330,163 +302,40 @@ public class InferredBasicValueResolver {
|
|||
}
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>, R> EnumeratedValueResolution<E,R> fromEnum(
|
||||
public static <E extends Enum<E>> BasicValue.Resolution<E> fromEnum(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
BasicJavaType<R> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
final EnumType enumStyle = stdIndicators.getEnumeratedType();
|
||||
if ( enumStyle == null ) {
|
||||
// NOTE : separate from the explicit ORDINAL check to facilitate
|
||||
// handling native database enum types. In theory anyway - atm
|
||||
// we cannot discern an implicit (default value) or explicit style
|
||||
// due to HCANN and annotation handling for default values
|
||||
|
||||
//noinspection unchecked
|
||||
return (EnumeratedValueResolution<E, R>) ordinalEnumValueResolution(
|
||||
enumJavaType,
|
||||
(BasicJavaType<? extends Number>)explicitJavaType,
|
||||
explicitJdbcType,
|
||||
context
|
||||
);
|
||||
}
|
||||
switch ( enumStyle ) {
|
||||
case STRING:
|
||||
//noinspection unchecked
|
||||
return (EnumeratedValueResolution<E, R>) stringEnumValueResolution(
|
||||
enumJavaType,
|
||||
explicitJavaType,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
context
|
||||
);
|
||||
case ORDINAL:
|
||||
//noinspection unchecked
|
||||
return (EnumeratedValueResolution<E, R>) ordinalEnumValueResolution(
|
||||
enumJavaType,
|
||||
(BasicJavaType<? extends Number>)explicitJavaType,
|
||||
explicitJdbcType,
|
||||
context
|
||||
);
|
||||
default:
|
||||
throw new MappingException( "Unknown enumeration-style (JPA EnumType) : " + enumStyle );
|
||||
}
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>, N extends Number> EnumeratedValueResolution<E,N> ordinalEnumValueResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
BasicJavaType<N> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
MetadataBuildingContext context) {
|
||||
final JdbcType jdbcType = ordinalJdbcType( explicitJdbcType, enumJavaType, context );
|
||||
final JavaType<N> relationalJavaType = ordinalJavaType( explicitJavaType, jdbcType, context );
|
||||
return new EnumeratedValueResolution<>(
|
||||
jdbcType,
|
||||
new OrdinalEnumValueConverter<>( enumJavaType, jdbcType, relationalJavaType )
|
||||
);
|
||||
}
|
||||
|
||||
private static JdbcType ordinalJdbcType(
|
||||
JdbcType explicitJdbcType,
|
||||
EnumJavaType<?> enumJavaType,
|
||||
MetadataBuildingContext context) {
|
||||
return explicitJdbcType != null
|
||||
? explicitJdbcType
|
||||
: context.getMetadataCollector().getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( enumJavaType.hasManyValues() ? SMALLINT : TINYINT );
|
||||
}
|
||||
|
||||
private static <N extends Number> JavaType<N> ordinalJavaType(
|
||||
JavaType<N> explicitJavaType,
|
||||
JdbcType jdbcType,
|
||||
MetadataBuildingContext context) {
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( !Integer.class.isAssignableFrom( explicitJavaType.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
"Explicit JavaType [" + explicitJavaType +
|
||||
"] applied to enumerated value with EnumType#ORDINAL" +
|
||||
" should handle `java.lang.Integer` as its relational type descriptor"
|
||||
);
|
||||
}
|
||||
return explicitJavaType;
|
||||
}
|
||||
else {
|
||||
return jdbcType.getJdbcRecommendedJavaTypeMapping(
|
||||
null,
|
||||
null,
|
||||
context.getMetadataCollector().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> EnumeratedValueResolution<E,?> stringEnumValueResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
BasicJavaType<?> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
BootstrapContext bootstrapContext) {
|
||||
final JdbcType jdbcType = explicitJdbcType == null
|
||||
? enumJavaType.getRecommendedJdbcType( stdIndicators )
|
||||
: explicitJdbcType;
|
||||
final EnumValueConverter<E,?> converter;
|
||||
if ( jdbcType instanceof NativeEnumJdbcType ) {
|
||||
converter = new NativeEnumValueConverter<>( enumJavaType, jdbcType, new ObjectJavaType() {
|
||||
@Override
|
||||
public <X> X unwrap(Object value, Class<X> type, WrapperOptions options) {
|
||||
if ( String.class.equals(type) && value instanceof Enum) {
|
||||
return (X) ((Enum<?>) value).name();
|
||||
}
|
||||
else {
|
||||
return super.unwrap(value, type, options);
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
else {
|
||||
converter = new NamedEnumValueConverter<>(
|
||||
final BasicTypeImpl<E> basicType = new BasicTypeImpl<>( enumJavaType, jdbcType );
|
||||
bootstrapContext.registerAdHocBasicType( basicType );
|
||||
return new InferredBasicValueResolution<>(
|
||||
basicType,
|
||||
enumJavaType,
|
||||
enumJavaType,
|
||||
jdbcType,
|
||||
stringJavaType( explicitJavaType, stdIndicators, context )
|
||||
basicType,
|
||||
ImmutableMutabilityPlan.instance()
|
||||
);
|
||||
}
|
||||
return new EnumeratedValueResolution<>( jdbcType, converter );
|
||||
}
|
||||
|
||||
private static JavaType<String> stringJavaType(
|
||||
BasicJavaType<?> explicitJavaType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( ! String.class.isAssignableFrom( explicitJavaType.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
"Explicit JavaType [" + explicitJavaType +
|
||||
"] applied to enumerated value with EnumType#STRING" +
|
||||
" should handle `java.lang.String` as its relational type descriptor"
|
||||
);
|
||||
}
|
||||
return (JavaType<String>) explicitJavaType;
|
||||
}
|
||||
else {
|
||||
return context.getMetadataCollector().getTypeConfiguration().getJavaTypeRegistry()
|
||||
.getDescriptor( stdIndicators.getColumnLength() == 1 ? Character.class : String.class );
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> InferredBasicValueResolution<T,T> fromTemporal(
|
||||
public static <T> BasicValue.Resolution<T> fromTemporal(
|
||||
TemporalJavaType<T> reflectedJtd,
|
||||
BasicJavaType<?> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
Type resolvedJavaType,
|
||||
Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
JdbcTypeIndicators stdIndicators) {
|
||||
final TypeConfiguration typeConfiguration = stdIndicators.getTypeConfiguration();
|
||||
final TemporalType requestedTemporalPrecision = stdIndicators.getTemporalPrecision();
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Case #1 - explicit JavaType
|
||||
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( !JavaTypeHelper.isTemporal( explicitJavaType ) ) {
|
||||
if ( !isTemporal( explicitJavaType ) ) {
|
||||
throw new MappingException(
|
||||
"Explicit JavaType [" + explicitJavaType +
|
||||
"] defined for temporal value must implement TemporalJavaType"
|
||||
|
@ -495,7 +344,6 @@ public class InferredBasicValueResolver {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
final TemporalJavaType<T> explicitTemporalJtd = (TemporalJavaType<T>) explicitJavaType;
|
||||
|
||||
if ( requestedTemporalPrecision != null && explicitTemporalJtd.getPrecision() != requestedTemporalPrecision ) {
|
||||
throw new MappingException(
|
||||
"Temporal precision (`jakarta.persistence.TemporalType`) mismatch... requested precision = " + requestedTemporalPrecision +
|
||||
|
@ -507,9 +355,7 @@ public class InferredBasicValueResolver {
|
|||
final JdbcType jdbcType = explicitJdbcType != null
|
||||
? explicitJdbcType
|
||||
: explicitTemporalJtd.getRecommendedJdbcType( stdIndicators );
|
||||
|
||||
final BasicType<T> jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( explicitTemporalJtd, jdbcType );
|
||||
|
||||
final MutabilityPlan<T> mutabilityPlan = determineMutabilityPlan( explicitMutabilityPlanAccess, explicitTemporalJtd, typeConfiguration );
|
||||
return new InferredBasicValueResolution<>(
|
||||
jdbcMapping,
|
||||
|
@ -531,10 +377,7 @@ public class InferredBasicValueResolver {
|
|||
final TemporalJavaType<T> jtd;
|
||||
|
||||
if ( requestedTemporalPrecision != null ) {
|
||||
jtd = reflectedJtd.resolveTypeForPrecision(
|
||||
requestedTemporalPrecision,
|
||||
typeConfiguration
|
||||
);
|
||||
jtd = reflectedJtd.resolveTypeForPrecision( requestedTemporalPrecision, typeConfiguration );
|
||||
}
|
||||
else {
|
||||
jtd = reflectedJtd;
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
|||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
|
@ -64,7 +63,7 @@ import jakarta.persistence.AttributeConverter;
|
|||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface InFlightMetadataCollector extends Mapping, MetadataImplementor {
|
||||
public interface InFlightMetadataCollector extends MetadataImplementor {
|
||||
BootstrapContext getBootstrapContext();
|
||||
|
||||
/**
|
||||
|
|
|
@ -204,6 +204,7 @@ import static org.hibernate.cfg.AvailableSettings.NON_CONTEXTUAL_LOB_CREATION;
|
|||
import static org.hibernate.cfg.AvailableSettings.STATEMENT_BATCH_SIZE;
|
||||
import static org.hibernate.cfg.AvailableSettings.USE_GET_GENERATED_KEYS;
|
||||
import static org.hibernate.internal.util.StringHelper.parseCommaSeparatedString;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY;
|
||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
||||
import static org.hibernate.type.SqlTypes.BIGINT;
|
||||
import static org.hibernate.type.SqlTypes.BINARY;
|
||||
|
@ -762,7 +763,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
}
|
||||
|
||||
public String[] getCreateEnumTypeCommand(String name, String[] values) {
|
||||
return null;
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
public String[] getCreateEnumTypeCommand(Class<? extends Enum<?>> enumType) {
|
||||
|
@ -771,6 +772,14 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
return getCreateEnumTypeCommand( enumType.getSimpleName(), values );
|
||||
}
|
||||
|
||||
public String[] getDropEnumTypeCommand(String name) {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
public String[] getDropEnumTypeCommand(Class<? extends Enum<?>> enumType) {
|
||||
return getDropEnumTypeCommand( enumType.getSimpleName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a SQL check condition for a column that represents an enumerated value
|
||||
* by its {@linkplain jakarta.persistence.EnumType#STRING string representation}.
|
||||
|
|
|
@ -76,6 +76,7 @@ import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.NativeEnumDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
@ -378,6 +379,8 @@ public class MySQLDialect extends Dialect {
|
|||
.withTypeCapacity( maxLobLen, "text" )
|
||||
.build()
|
||||
);
|
||||
|
||||
ddlTypeRegistry.addDescriptor( new NativeEnumDdlTypeImpl(this) );
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
@ -641,6 +644,8 @@ public class MySQLDialect extends Dialect {
|
|||
.getDescriptor( Object.class )
|
||||
)
|
||||
);
|
||||
|
||||
jdbcTypeRegistry.addDescriptor( new MySQLEnumJdbcType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -869,6 +874,11 @@ public class MySQLDialect extends Dialect {
|
|||
return getMySQLVersion().isSameOrAfter( 8, 0, 16 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNativeEnums() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEnumTypeDeclaration(String name, String[] values) {
|
||||
StringBuilder type = new StringBuilder();
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterCharacterData;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class MySQLEnumJdbcType implements JdbcType {
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return new JdbcLiteralFormatterCharacterData<>( javaType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "ENUM";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( index, getJavaType().unwrap( value, String.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( name, getJavaType().unwrap( value, String.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( rs.getString( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getString( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BooleanJdbcType;
|
||||
|
||||
|
@ -14,7 +15,7 @@ public class OracleBooleanJdbcType extends BooleanJdbcType {
|
|||
public static final OracleBooleanJdbcType INSTANCE = new OracleBooleanJdbcType();
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, Dialect dialect) {
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
return columnName + " in (0,1)";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
||||
|
@ -41,7 +42,7 @@ public class OracleJsonJdbcType extends OracleJsonBlobJdbcType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, Dialect dialect) {
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
// No check constraint necessary, because the JSON DDL type is already OSON encoded
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ import org.hibernate.type.descriptor.jdbc.XmlJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.NamedNativeEnumDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -271,6 +272,8 @@ public class PostgreSQLDialect extends Dialect {
|
|||
|
||||
// Prefer jsonb if possible
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) );
|
||||
|
||||
ddlTypeRegistry.addDescriptor( new NamedNativeEnumDdlTypeImpl( this ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -421,6 +424,11 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return new String[] { type.toString(), cast1.toString(), cast2.toString() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDropEnumTypeCommand(String name) {
|
||||
return new String[] { "drop type if exists " + name + " cascade" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currentTime() {
|
||||
return "localtime";
|
||||
|
@ -1408,6 +1416,8 @@ public class PostgreSQLDialect extends Dialect {
|
|||
.getDescriptor( Object.class )
|
||||
)
|
||||
);
|
||||
|
||||
jdbcTypeRegistry.addDescriptor( new PostgreSQLEnumJdbcType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class PostgreSQLEnumJdbcType implements JdbcType {
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return (appender, value, dialect, wrapperOptions) -> appender.appendSql( "'" + ((Enum<?>) value).name() + "'::"
|
||||
+ dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "ENUM";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnumTypeDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||
st.setNull( index, Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||
st.setNull( name, Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, value, Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, value, Types.OTHER );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( rs.getObject( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getObject( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getObject( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(JavaType<?> javaType, InFlightMetadataCollector metadataCollector) {
|
||||
Database database = metadataCollector.getDatabase();
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
String name = enumClass.getSimpleName();
|
||||
String[] create = database.getDialect().getCreateEnumTypeCommand( enumClass );
|
||||
if ( create != null ) {
|
||||
String[] drop = database.getDialect().getDropEnumTypeCommand( enumClass );
|
||||
database.addAuxiliaryDatabaseObject(
|
||||
new NamedAuxiliaryDatabaseObject( name, database.getDefaultNamespace(), create, drop, emptySet(), true )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,15 +20,12 @@ import org.hibernate.boot.model.TypeDefinition;
|
|||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
||||
import org.hibernate.boot.model.process.internal.EnumeratedValueResolution;
|
||||
import org.hibernate.boot.model.process.internal.InferredBasicValueResolution;
|
||||
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
|
||||
import org.hibernate.boot.model.process.internal.NamedBasicTypeResolution;
|
||||
import org.hibernate.boot.model.process.internal.NamedConverterResolution;
|
||||
import org.hibernate.boot.model.process.internal.UserTypeResolution;
|
||||
import org.hibernate.boot.model.process.internal.VersionResolution;
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
|
@ -320,18 +317,11 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
resolveColumn( (Column) selectable, getDialect() );
|
||||
}
|
||||
|
||||
Database database = getBuildingContext().getMetadataCollector().getDatabase();
|
||||
BasicValueConverter<?, ?> valueConverter = resolution.getValueConverter();
|
||||
if ( valueConverter != null ) {
|
||||
AuxiliaryDatabaseObject udt = valueConverter.getAuxiliaryDatabaseObject(
|
||||
resolution.getJdbcType(),
|
||||
database.getDialect(),
|
||||
database.getDefaultNamespace()
|
||||
resolution.getJdbcType()
|
||||
.addAuxiliaryDatabaseObjects(
|
||||
resolution.getRelationalJavaType(),
|
||||
getBuildingContext().getMetadataCollector()
|
||||
);
|
||||
if ( udt != null ) {
|
||||
database.addAuxiliaryDatabaseObject( udt );
|
||||
}
|
||||
}
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
@ -605,9 +595,9 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
);
|
||||
}
|
||||
|
||||
if ( name.startsWith( EnumeratedValueResolution.PREFIX ) ) {
|
||||
return EnumeratedValueResolution.fromName( name, stdIndicators, context );
|
||||
}
|
||||
// if ( name.startsWith( EnumeratedValueResolution.PREFIX ) ) {
|
||||
// return EnumeratedValueResolution.fromName( name, stdIndicators, context );
|
||||
// }
|
||||
|
||||
if ( name.startsWith( BasicTypeImpl.EXTERNALIZED_PREFIX ) ) {
|
||||
final BasicTypeImpl<Object> basicType = context.getBootstrapContext().resolveAdHocBasicType( name );
|
||||
|
|
|
@ -273,8 +273,9 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
try {
|
||||
final Type type = getValue().getType();
|
||||
sqlTypeName = isArray( type )
|
||||
//TODO: remove the special case for array types, this should be handled by the DdlType!
|
||||
? dialect.getArrayTypeName( getArrayElementTypeName( dialect, ddlTypeRegistry, getArrayElementType( type ) ) )
|
||||
: ddlTypeRegistry.getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ) );
|
||||
: ddlTypeRegistry.getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ), getUnderlyingType( mapping, type, typeIndex ) );
|
||||
}
|
||||
catch ( Exception cause ) {
|
||||
throw new MappingException(
|
||||
|
@ -291,6 +292,27 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
return sqlTypeName;
|
||||
}
|
||||
|
||||
private static Type getUnderlyingType(Mapping mapping, Type type, int typeIndex) {
|
||||
if ( type.isComponentType() ) {
|
||||
int cols = 0;
|
||||
for ( Type subtype : ((ComponentType) type).getSubtypes() ) {
|
||||
int columnSpan = subtype.getColumnSpan( mapping );
|
||||
if ( cols+columnSpan > typeIndex ) {
|
||||
return getUnderlyingType( mapping, subtype, typeIndex-cols );
|
||||
}
|
||||
cols += columnSpan;
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
else if ( type.isEntityType() ) {
|
||||
Type idType = ((EntityType) type).getIdentifierOrUniqueKeyType(mapping);
|
||||
return getUnderlyingType( mapping, idType, typeIndex );
|
||||
}
|
||||
else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
private String getArrayElementTypeName(Dialect dialect, DdlTypeRegistry ddlTypeRegistry, BasicType<?> elementType) {
|
||||
return ddlTypeRegistry.getTypeName(
|
||||
elementType.getJdbcType().getDdlTypeCode(),
|
||||
|
|
|
@ -42,8 +42,8 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.TupleType;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||
|
@ -150,6 +150,7 @@ import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
|||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeHelper;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -1122,7 +1123,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmExpression<Number> quot(Number x, Expression<? extends Number> y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.QUOT,
|
||||
|
@ -1209,7 +1209,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
return new SqmLiteralNull<>( this );
|
||||
}
|
||||
|
||||
final SqmExpressible<T> expressible = resolveInferredType( value, typeInferenceSource, getTypeConfiguration() );
|
||||
SqmExpressible<T> expressible = resolveInferredType( value, typeInferenceSource, getTypeConfiguration() );
|
||||
if ( expressible.getExpressibleJavaType().isInstance( value ) ) {
|
||||
return new SqmLiteral<>( value, expressible, this );
|
||||
}
|
||||
|
@ -1228,21 +1228,27 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes","unchecked"})
|
||||
private static <T> SqmExpressible<T> resolveInferredType(
|
||||
T value,
|
||||
SqmExpression<? extends T> typeInferenceSource,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( typeInferenceSource != null ) {
|
||||
//noinspection unchecked
|
||||
return (SqmExpressible<T>) typeInferenceSource.getNodeType();
|
||||
}
|
||||
|
||||
if ( value == null ) {
|
||||
else if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (BasicType<T>) typeConfiguration.getBasicTypeForJavaType( value.getClass() );
|
||||
else {
|
||||
Class type = value.getClass();
|
||||
BasicType<T> result = typeConfiguration.getBasicTypeForJavaType( type );
|
||||
if ( result == null && value instanceof Enum ) {
|
||||
return new BasicTypeImpl<>( new EnumJavaType<>( type ) );
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1770,7 +1776,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
if ( value instanceof SqmExpression ) {
|
||||
return (SqmExpression<T>) value;
|
||||
}
|
||||
if ( criteriaValueHandlingMode == ValueHandlingMode.INLINE ) {
|
||||
if ( inlineValue( value ) ) {
|
||||
return literal( value, typeInferenceSource );
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1852,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
if ( value instanceof SqmExpression ) {
|
||||
return (SqmExpression<T>) value;
|
||||
}
|
||||
if ( criteriaValueHandlingMode == ValueHandlingMode.INLINE ) {
|
||||
if ( inlineValue( value ) ) {
|
||||
return literal( value );
|
||||
}
|
||||
else {
|
||||
|
@ -1858,6 +1864,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
}
|
||||
|
||||
private <T> boolean inlineValue(T value) {
|
||||
return criteriaValueHandlingMode == ValueHandlingMode.INLINE || value instanceof Enum
|
||||
&& queryEngine.getCriteriaBuilder().getSessionFactory().getJdbcServices().getDialect().hasNativeEnums();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V, C extends Collection<V>> SqmExpression<Collection<V>> values(C collection) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -1905,7 +1916,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y> JpaCoalesce<Y> coalesce(Expression<? extends Y> x, Y y) {
|
||||
//noinspection unchecked
|
||||
return coalesce( x, value( y, (SqmExpression<? extends Y>) x ) );
|
||||
}
|
||||
|
||||
|
@ -2063,7 +2073,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Expression<? extends Y> lower, Expression<? extends Y> upper) {
|
||||
assertComparable( value, lower );
|
||||
assertComparable( value, upper );
|
||||
//noinspection unchecked
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression<? extends Y>) value,
|
||||
(SqmExpression<? extends Y>) lower,
|
||||
|
@ -2074,7 +2083,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Y lower, Y upper) {
|
||||
final SqmExpression<? extends Y> valueExpression = (SqmExpression<? extends Y>) value;
|
||||
final SqmExpression<?> lowerExpr = value( lower, valueExpression );
|
||||
|
@ -2208,7 +2216,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
|
@ -2232,7 +2239,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
|||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
|
@ -200,7 +201,7 @@ public class ArgumentTypesValidator implements ArgumentsValidator {
|
|||
}
|
||||
break;
|
||||
case STRING:
|
||||
if ( !isCharacterType(code) && code != ENUM_UNKNOWN_JDBC_TYPE ) {
|
||||
if ( !isCharacterType(code) && code != SqlTypes.ENUM && code != ENUM_UNKNOWN_JDBC_TYPE) {
|
||||
throwError(type, javaType, functionName, count);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -392,14 +392,11 @@ import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
|
|||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeHelper;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.internal.ConvertedBasicTypeImpl;
|
||||
import org.hibernate.type.internal.BasicTypeImpl;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.usertype.UserVersionType;
|
||||
import org.hibernate.usertype.internal.AbstractTimeZoneStorageCompositeUserType;
|
||||
|
@ -410,6 +407,7 @@ import jakarta.persistence.TemporalType;
|
|||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.hibernate.generator.EventType.INSERT;
|
||||
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
|
||||
import static org.hibernate.query.sqm.BinaryArithmeticOperator.ADD;
|
||||
|
@ -2213,7 +2211,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
if ( selectionNode instanceof SqmPath<?> ) {
|
||||
prepareForSelection( (SqmPath<?>) selectionNode );
|
||||
}
|
||||
resultProducers = Collections.singletonList(
|
||||
resultProducers = singletonList(
|
||||
new AbstractMap.SimpleEntry<>(
|
||||
sqmSelection.getAlias(),
|
||||
(DomainResultProducer<?>) selectionNode.accept( this )
|
||||
|
@ -4236,7 +4234,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(
|
||||
functionDescriptor.getName(),
|
||||
functionDescriptor,
|
||||
Collections.singletonList( new QueryLiteral<>( 1, integerType ) ),
|
||||
singletonList( new QueryLiteral<>( 1, integerType ) ),
|
||||
null,
|
||||
integerType,
|
||||
integerType
|
||||
|
@ -4585,7 +4583,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
arguments = subQueryColumns;
|
||||
}
|
||||
else {
|
||||
arguments = Collections.singletonList( new SqlTuple( subQueryColumns, modelPart ) );
|
||||
arguments = singletonList( new SqlTuple( subQueryColumns, modelPart ) );
|
||||
}
|
||||
final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(
|
||||
functionDescriptor.getName(),
|
||||
|
@ -4707,7 +4705,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return new SelfRenderingFunctionSqlAstExpression(
|
||||
pathName,
|
||||
(sqlAppender, sqlAstArguments, walker) -> sqlAstArguments.get( 0 ).accept( walker ),
|
||||
Collections.singletonList(
|
||||
singletonList(
|
||||
new ColumnReference(
|
||||
identifierVariable,
|
||||
tableReference.getColumnNames().get( 0 ),
|
||||
|
@ -4897,10 +4895,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
else {
|
||||
keyExpressible.forEachJdbcType(
|
||||
(index, jdbcMapping) -> expressions.add(
|
||||
new QueryLiteral<>(
|
||||
null,
|
||||
(BasicValuedMapping) jdbcMapping
|
||||
)
|
||||
new QueryLiteral<>( null, (BasicValuedMapping) jdbcMapping )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -4951,10 +4946,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
)
|
||||
);
|
||||
}
|
||||
return new QueryLiteral<>(
|
||||
sqlLiteralValue,
|
||||
basicValuedMapping
|
||||
);
|
||||
return new QueryLiteral<>( sqlLiteralValue, basicValuedMapping );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6472,35 +6464,27 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
@Override
|
||||
public Object visitEnumLiteral(SqmEnumLiteral<?> sqmEnumLiteral) {
|
||||
final BasicValuedMapping inferrableType = (BasicValuedMapping) resolveInferredType();
|
||||
if ( inferrableType != null ) {
|
||||
final Object jdbcValue = inferrableType.getJdbcMapping().convertToRelationalValue( sqmEnumLiteral.getEnumValue() );
|
||||
return new QueryLiteral<>( jdbcValue, inferrableType );
|
||||
final BasicValuedMapping inferredType = (BasicValuedMapping) resolveInferredType();
|
||||
if ( inferredType != null ) {
|
||||
return new QueryLiteral<>(
|
||||
inferredType.getJdbcMapping().convertToRelationalValue( sqmEnumLiteral.getEnumValue() ),
|
||||
inferredType
|
||||
);
|
||||
}
|
||||
else {
|
||||
// This can only happen when selecting an enum literal, in which case we default to ordinal encoding
|
||||
final EnumJavaType<?> enumJtd = sqmEnumLiteral.getExpressibleJavaType();
|
||||
final TypeConfiguration typeConfiguration = getTypeConfiguration();
|
||||
final JdbcType jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SMALLINT );
|
||||
final JavaType<Number> relationalJtd = typeConfiguration.getJavaTypeRegistry().getDescriptor( Integer.class );
|
||||
|
||||
return queryLiteral( sqmEnumLiteral, enumJtd, typeConfiguration, jdbcType, relationalJtd );
|
||||
return queryLiteral( sqmEnumLiteral, getTypeConfiguration() );
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Enum<T>, N extends Number> QueryLiteral<Integer> queryLiteral(
|
||||
SqmEnumLiteral<?> sqmEnumLiteral,
|
||||
EnumJavaType<T> enumJtd,
|
||||
TypeConfiguration typeConfiguration,
|
||||
JdbcType jdbcType,
|
||||
JavaType<N> relationalJtd) {
|
||||
private static <T extends Enum<T>> QueryLiteral<T> queryLiteral(
|
||||
SqmEnumLiteral<T> sqmEnumLiteral,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return new QueryLiteral<>(
|
||||
sqmEnumLiteral.getEnumValue().ordinal(),
|
||||
new ConvertedBasicTypeImpl<>(
|
||||
null,
|
||||
"Query literal implicit Enum type descriptor",
|
||||
jdbcType,
|
||||
new OrdinalEnumValueConverter<>( enumJtd, jdbcType, relationalJtd )
|
||||
sqmEnumLiteral.getEnumValue(),
|
||||
new BasicTypeImpl<>(
|
||||
sqmEnumLiteral.getExpressibleJavaType(),
|
||||
typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SMALLINT )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
|||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
|
@ -33,7 +32,6 @@ public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
|
|||
private final BasicValuedMapping type;
|
||||
|
||||
public QueryLiteral(T value, BasicValuedMapping type) {
|
||||
assert value == null || type.getJdbcMapping().getJdbcJavaType().isInstance( value );
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
@ -62,9 +60,8 @@ public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
|
|||
public DomainResult<T> createDomainResult(
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState()
|
||||
.getSqlExpressionResolver();
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
final SqlSelection sqlSelection = creationState.getSqlAstCreationState().getSqlExpressionResolver()
|
||||
.resolveSqlSelection(
|
||||
this,
|
||||
type.getJdbcMapping().getJdbcJavaType(),
|
||||
null,
|
||||
|
|
|
@ -159,6 +159,15 @@ public interface BasicType<T> extends Type, BasicDomainType<T>, MappingType, Bas
|
|||
checkCondition = getJdbcType().getCheckCondition(
|
||||
columnName,
|
||||
getMappedJavaType(),
|
||||
valueConverter,
|
||||
dialect
|
||||
);
|
||||
}
|
||||
if ( checkCondition == null ) {
|
||||
checkCondition = getMappedJavaType().getCheckCondition(
|
||||
columnName,
|
||||
getJdbcType(),
|
||||
valueConverter,
|
||||
dialect
|
||||
);
|
||||
}
|
||||
|
|
|
@ -522,6 +522,13 @@ public class SqlTypes {
|
|||
*/
|
||||
public static final int GEOGRAPHY = 3250;
|
||||
|
||||
/**
|
||||
* A type code representing a SQL {@code ENUM} type.
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
public static final int ENUM = 6000;
|
||||
|
||||
private SqlTypes() {
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ package org.hibernate.type.descriptor.converter.internal;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class EnumHelper {
|
||||
public static final String[] getEnumeratedValues(Class<? extends Enum<?>> enumClass) {
|
||||
public static String[] getEnumeratedValues(Class<? extends Enum<?>> enumClass) {
|
||||
Enum<?>[] values = enumClass.getEnumConstants();
|
||||
String[] names = new String[values.length];
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
|
|
|
@ -8,23 +8,20 @@ package org.hibernate.type.descriptor.converter.internal;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
/**
|
||||
* BasicValueConverter handling the conversion of an enum based on
|
||||
* JPA {@link jakarta.persistence.EnumType#STRING} strategy (storing the name)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated we no longer use converters to handle enum mappings
|
||||
*/
|
||||
@Deprecated(since="6.3", forRemoval=true)
|
||||
public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConverter<E,String>, Serializable {
|
||||
private final EnumJavaType<E> domainTypeDescriptor;
|
||||
private final JdbcType jdbcType;
|
||||
|
@ -68,28 +65,4 @@ public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConv
|
|||
public String toSqlLiteral(Object value) {
|
||||
return "'" + ( (Enum<?>) value ).name() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JdbcType jdbcType, Dialect dialect) {
|
||||
return dialect.getCheckCondition( columnName, getDomainJavaType().getJavaTypeClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecializedTypeDeclaration(JdbcType jdbcType, Dialect dialect) {
|
||||
return dialect.getEnumTypeDeclaration( getDomainJavaType().getJavaTypeClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuxiliaryDatabaseObject getAuxiliaryDatabaseObject(JdbcType jdbcType, Dialect dialect, Namespace defaultNamespace) {
|
||||
Class<? extends Enum<?>> enumClass = getDomainJavaType().getJavaTypeClass();
|
||||
String name = enumClass.getSimpleName();
|
||||
String[] create = dialect.getCreateEnumTypeCommand( enumClass );
|
||||
if ( create != null ) {
|
||||
String[] drop = new String[] { "drop type " + name + " cascade" }; //TODO: move to Dialect
|
||||
return new NamedAuxiliaryDatabaseObject( name, defaultNamespace, create, drop, emptySet(), true );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.type.descriptor.converter.internal;
|
||||
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
/**
|
||||
* BasicValueConverter handling the conversion of an enum based on
|
||||
* JPA {@link jakarta.persistence.EnumType#STRING} strategy (storing the name)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NativeEnumValueConverter<E extends Enum<E>> implements EnumValueConverter<E,Object>, Serializable {
|
||||
private final EnumJavaType<E> domainTypeDescriptor;
|
||||
private final JdbcType jdbcType;
|
||||
private final JavaType<Object> relationalTypeDescriptor;
|
||||
|
||||
public NativeEnumValueConverter(
|
||||
EnumJavaType<E> domainTypeDescriptor,
|
||||
JdbcType jdbcType,
|
||||
JavaType<Object> relationalTypeDescriptor) {
|
||||
this.domainTypeDescriptor = domainTypeDescriptor;
|
||||
this.jdbcType = jdbcType;
|
||||
this.relationalTypeDescriptor = relationalTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumJavaType<E> getDomainJavaType() {
|
||||
return domainTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<Object> getRelationalJavaType() {
|
||||
return relationalTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E toDomainValue(Object relationalForm) {
|
||||
return relationalForm instanceof String
|
||||
? domainTypeDescriptor.fromName( (String) relationalForm )
|
||||
: (E) relationalForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toRelationalValue(E domainForm) {
|
||||
return domainForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return jdbcType.getDefaultSqlTypeCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlLiteral(Object value) {
|
||||
return "'" + ( (Enum<?>) value ).name() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JdbcType jdbcType, Dialect dialect) {
|
||||
return dialect.getCheckCondition( columnName, getDomainJavaType().getJavaTypeClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecializedTypeDeclaration(JdbcType jdbcType, Dialect dialect) {
|
||||
return dialect.getEnumTypeDeclaration( getDomainJavaType().getJavaTypeClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuxiliaryDatabaseObject getAuxiliaryDatabaseObject(JdbcType jdbcType, Dialect dialect, Namespace defaultNamespace) {
|
||||
Class<? extends Enum<?>> enumClass = getDomainJavaType().getJavaTypeClass();
|
||||
String name = enumClass.getSimpleName();
|
||||
String[] create = dialect.getCreateEnumTypeCommand( enumClass );
|
||||
if ( create != null ) {
|
||||
String[] drop = new String[] { "drop type " + name + " cascade" }; //TODO: move to Dialect
|
||||
return new NamedAuxiliaryDatabaseObject( name, defaultNamespace, create, drop, emptySet(), true );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ package org.hibernate.type.descriptor.converter.internal;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
@ -19,7 +18,10 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
|||
* JPA {@link jakarta.persistence.EnumType#ORDINAL} strategy (storing the ordinal)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated we no longer use converters to handle enum mappings
|
||||
*/
|
||||
@Deprecated(since="6.3", forRemoval=true)
|
||||
public class OrdinalEnumValueConverter<E extends Enum<E>, N extends Number> implements EnumValueConverter<E, N>, Serializable {
|
||||
|
||||
private final EnumJavaType<E> enumJavaType;
|
||||
|
@ -64,10 +66,4 @@ public class OrdinalEnumValueConverter<E extends Enum<E>, N extends Number> impl
|
|||
public String toSqlLiteral(Object value) {
|
||||
return Integer.toString( ( (Enum<?>) value ).ordinal() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JdbcType jdbcType, Dialect dialect) {
|
||||
int max = getDomainJavaType().getJavaTypeClass().getEnumConstants().length - 1;
|
||||
return dialect.getCheckCondition( columnName, 0, max );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
package org.hibernate.type.descriptor.converter.spi;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -68,9 +66,4 @@ public interface BasicValueConverter<D,R> {
|
|||
default String getSpecializedTypeDeclaration(JdbcType jdbcType, Dialect dialect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Incubating
|
||||
default AuxiliaryDatabaseObject getAuxiliaryDatabaseObject(JdbcType jdbcType, Dialect dialect, Namespace defaultNamespace) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,15 @@ package org.hibernate.type.descriptor.java;
|
|||
import jakarta.persistence.EnumType;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.descriptor.jdbc.NativeEnumJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import static jakarta.persistence.EnumType.ORDINAL;
|
||||
import static org.hibernate.type.SqlTypes.CHAR;
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
import static org.hibernate.type.SqlTypes.NCHAR;
|
||||
import static org.hibernate.type.SqlTypes.NVARCHAR;
|
||||
import static org.hibernate.type.SqlTypes.SMALLINT;
|
||||
|
@ -35,7 +36,6 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
|
||||
@Override
|
||||
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
|
||||
final JdbcTypeRegistry registry = context.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
final EnumType type = context.getEnumeratedType();
|
||||
int sqlType;
|
||||
switch ( type == null ? ORDINAL : type ) {
|
||||
|
@ -44,7 +44,7 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
break;
|
||||
case STRING:
|
||||
if ( context.getDialect().hasNativeEnums() ) {
|
||||
return NativeEnumJdbcType.INSTANCE;
|
||||
sqlType = ENUM;
|
||||
}
|
||||
else if ( context.getColumnLength() == 1 ) {
|
||||
sqlType = context.isNationalized() ? NCHAR : CHAR;
|
||||
|
@ -56,7 +56,7 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
default:
|
||||
throw new AssertionFailure("unknown EnumType");
|
||||
}
|
||||
return registry.getDescriptor( sqlType );
|
||||
return context.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( sqlType );
|
||||
}
|
||||
|
||||
public boolean hasManyValues() {
|
||||
|
@ -254,4 +254,21 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JdbcType jdbcType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
if ( converter != null ) {
|
||||
//TODO: actually convert the enum values to create the check constraint
|
||||
return null;
|
||||
}
|
||||
else if ( jdbcType.isInteger() ) {
|
||||
int max = getJavaTypeClass().getEnumConstants().length - 1;
|
||||
return dialect.getCheckCondition( columnName, 0, max );
|
||||
}
|
||||
else if ( jdbcType.isString() ) {
|
||||
return dialect.getCheckCondition( columnName, getJavaTypeClass() );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -332,4 +333,18 @@ public interface JavaType<T> extends Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The check constraint that should be added to the column
|
||||
* definition in generated DDL.
|
||||
*
|
||||
* @param columnName the name of the column
|
||||
* @param jdbcType the {@link JdbcType} of the mapped column
|
||||
* @param converter the converter, if any, or null
|
||||
* @param dialect the SQL {@link Dialect}
|
||||
* @return a check constraint condition or null
|
||||
* @since 6.2
|
||||
*/
|
||||
default String getCheckCondition(String columnName, JdbcType jdbcType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.sql.Types;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterNumericData;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.SQLException;
|
|||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.query.sqm.CastType;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.type.SqlTypes;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -156,11 +158,12 @@ public interface JdbcType extends Serializable {
|
|||
*
|
||||
* @param columnName the name of the column
|
||||
* @param javaType the {@link JavaType} of the mapped column
|
||||
* @param converter the converter, if any, or null
|
||||
* @param dialect the SQL {@link Dialect}
|
||||
* @return a check constraint condition or null
|
||||
* @since 6.2
|
||||
*/
|
||||
default String getCheckCondition(String columnName, JavaType<?> javaType, Dialect dialect) {
|
||||
default String getCheckCondition(String columnName, JavaType<?> javaType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -322,4 +325,8 @@ public interface JdbcType extends Serializable {
|
|||
default void registerOutParameter(CallableStatement callableStatement, int index) throws SQLException {
|
||||
callableStatement.registerOutParameter( index, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Incubating
|
||||
default void addAuxiliaryDatabaseObjects(JavaType<?> javaType, InFlightMetadataCollector metadataCollector) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
package org.hibernate.type.descriptor.jdbc;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class NativeEnumJdbcType extends VarcharJdbcType {
|
||||
|
||||
public static final NativeEnumJdbcType INSTANCE = new NativeEnumJdbcType();
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, value, SqlTypes.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, value, SqlTypes.OTHER );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return (X) rs.getObject( paramIndex );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return (X) statement.getObject( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return (X) statement.getObject( name );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import org.hibernate.type.SqlTypes;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -61,7 +62,7 @@ public class OracleJsonBlobJdbcType implements AggregateJdbcType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, Dialect dialect) {
|
||||
public String getCheckCondition(String columnName, JavaType<?> javaType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
return columnName + " is json";
|
||||
}
|
||||
|
||||
|
|
|
@ -89,5 +89,8 @@ public class JdbcTypeBaseline {
|
|||
target.addDescriptor( new LongVarcharJdbcType(SqlTypes.LONG32NVARCHAR) );
|
||||
|
||||
target.addDescriptor( RowIdJdbcType.INSTANCE );
|
||||
|
||||
// by default, map named enums to varchar columns
|
||||
target.addDescriptor( SqlTypes.ENUM, VarcharJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,32 +36,46 @@ public interface DdlType extends Serializable {
|
|||
*/
|
||||
int getSqlTypeCode();
|
||||
|
||||
default String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
return getTypeName( columnSize );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default type name without precision/length and scale parameters.
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
String getRawTypeName();
|
||||
|
||||
/**
|
||||
* Returns all type names without precision/length and scale parameters.
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Incubating
|
||||
@Deprecated(since = "6.3")
|
||||
default String[] getRawTypeNames() {
|
||||
return new String[] { getRawTypeName() };
|
||||
}
|
||||
|
||||
String getTypeNamePattern();
|
||||
|
||||
/**
|
||||
* Return a type with length, precision, and scale specified by the given
|
||||
* {@linkplain Size size object}.
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
default String getTypeName(Size size) {
|
||||
return getTypeName( size.getLength(), size.getPrecision(), size.getScale() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a type with the given length, precision, and scale.
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
String getTypeName(Long size, Integer precision, Integer scale);
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,11 +63,6 @@ public class DdlTypeImpl implements DdlType {
|
|||
return typeNamePattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeNamePattern() {
|
||||
return typeNamePattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Long size, Integer precision, Integer scale) {
|
||||
return replace( typeNamePattern, size, precision, scale );
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.type.descriptor.sql.internal;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NamedNativeEnumDdlTypeImpl implements DdlType {
|
||||
private final Dialect dialect;
|
||||
|
||||
public NamedNativeEnumDdlTypeImpl(Dialect dialect) {
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSqlTypeCode() {
|
||||
return ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) returnedClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawTypeName() {
|
||||
// this
|
||||
return "enum";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Long size, Integer precision, Integer scale) {
|
||||
throw new UnsupportedOperationException( "native enum type" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType, Long length, Integer precision, Integer scale) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.type.descriptor.sql.internal;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NativeEnumDdlTypeImpl implements DdlType {
|
||||
private final Dialect dialect;
|
||||
|
||||
public NativeEnumDdlTypeImpl(Dialect dialect) {
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSqlTypeCode() {
|
||||
return ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) returnedClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawTypeName() {
|
||||
// this
|
||||
return "enum";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Long size, Integer precision, Integer scale) {
|
||||
return "varchar(" + size + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType) {
|
||||
return "varchar";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastTypeName(JdbcType jdbcType, JavaType<?> javaType, Long length, Integer precision, Integer scale) {
|
||||
return getTypeName( length, precision, scale );
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -179,11 +180,28 @@ public class DdlTypeRegistry implements Serializable {
|
|||
*
|
||||
* @return the associated type name with the smallest capacity that accommodates
|
||||
* the given size, if available, and the default type name otherwise
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
public String getTypeName(int typeCode, Size size) {
|
||||
return getTypeName( typeCode, size.getLength(), size.getPrecision(), size.getScale() );
|
||||
}
|
||||
|
||||
public String getTypeName(int typeCode, Size columnSize, Type type) {
|
||||
final DdlType descriptor = getDescriptor( typeCode );
|
||||
if ( descriptor == null ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"No type mapping for org.hibernate.type.SqlTypes code: %s (%s)",
|
||||
typeCode,
|
||||
JdbcTypeNameMapper.getTypeName( typeCode )
|
||||
)
|
||||
);
|
||||
}
|
||||
return descriptor.getTypeName( columnSize, type.getReturnedClass() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL type name for the specified {@link java.sql.Types JDBC type code}
|
||||
* and size, filling in the placemarkers {@code $l}, {@code $p}, and {@code $s}
|
||||
|
@ -197,7 +215,10 @@ public class DdlTypeRegistry implements Serializable {
|
|||
*
|
||||
* @return the associated type name with the smallest capacity that accommodates
|
||||
* the given size, if available, and the default type name otherwise
|
||||
*
|
||||
* @deprecated not appropriate for named enum or array types
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
public String getTypeName(int typeCode, Long size, Integer precision, Integer scale) {
|
||||
final DdlType descriptor = getDescriptor( typeCode );
|
||||
if ( descriptor == null ) {
|
||||
|
@ -230,5 +251,4 @@ public class DdlTypeRegistry implements Serializable {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,11 +17,9 @@ import org.hibernate.mapping.SimpleValue;
|
|||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue