HHH-16311 - Migrate away from UserType for enum handling
This commit is contained in:
parent
8ee3be020b
commit
882e5d7622
|
@ -10,6 +10,10 @@ plugins {
|
|||
id 'org.hibernate.build.xjc-jakarta'
|
||||
}
|
||||
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
description = 'Hibernate\'s core ORM functionality'
|
||||
|
||||
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
|
||||
|
|
|
@ -6,66 +6,104 @@
|
|||
*/
|
||||
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.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
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.spi.JavaTypeRegistry;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
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.SMALLINT;
|
||||
import static org.hibernate.type.SqlTypes.TINYINT;
|
||||
|
||||
/**
|
||||
* 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>> implements BasicValue.Resolution<E> {
|
||||
private final CustomType<Object> enumTypeMapping;
|
||||
private final JavaType<E> domainJtd;
|
||||
private final JavaType<?> jdbcJtd;
|
||||
private final JdbcType jdbcType;
|
||||
private final EnumValueConverter<E,?> valueConverter;
|
||||
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(
|
||||
CustomType<Object> enumTypeMapping,
|
||||
JavaType<E> domainJtd,
|
||||
JavaType<?> jdbcJtd,
|
||||
JdbcType jdbcType,
|
||||
EnumValueConverter<E, ?> valueConverter) {
|
||||
this.enumTypeMapping = enumTypeMapping;
|
||||
this.domainJtd = domainJtd;
|
||||
this.jdbcJtd = jdbcJtd;
|
||||
this.jdbcType = jdbcType;
|
||||
EnumValueConverter<E, R> valueConverter,
|
||||
MetadataBuildingContext context) {
|
||||
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 ) {
|
||||
return EnumType.STRING;
|
||||
}
|
||||
else if ( valueConverter instanceof OrdinalEnumValueConverter ) {
|
||||
return EnumType.ORDINAL;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcMapping getJdbcMapping() {
|
||||
return enumTypeMapping;
|
||||
public ConvertedBasicType<E> getJdbcMapping() {
|
||||
return jdbcMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicType getLegacyResolvedBasicType() {
|
||||
return enumTypeMapping;
|
||||
public ConvertedBasicType<E> getLegacyResolvedBasicType() {
|
||||
return jdbcMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<E> getDomainJavaType() {
|
||||
return domainJtd;
|
||||
return jdbcMapping.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<?> getRelationalJavaType() {
|
||||
return jdbcJtd;
|
||||
return jdbcMapping.getJdbcJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcType getJdbcType() {
|
||||
return jdbcType;
|
||||
return jdbcMapping.getJdbcType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumValueConverter getValueConverter() {
|
||||
public EnumValueConverter<E,R> getValueConverter() {
|
||||
return valueConverter;
|
||||
}
|
||||
|
||||
|
@ -73,4 +111,60 @@ public class EnumeratedValueResolution<E extends Enum<E>> implements BasicValue.
|
|||
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 ] );
|
||||
|
||||
//noinspection unchecked,rawtypes
|
||||
final EnumJavaType<E> enumJavaType = (EnumJavaType) javaTypeRegistry.getDescriptor( enumClass );
|
||||
final JdbcType jdbcType;
|
||||
final EnumValueConverter<E,?> converter;
|
||||
|
||||
if ( style == EnumType.ORDINAL ) {
|
||||
jdbcType = jdbcTypeRegistry.getDescriptor( enumJavaType.hasManyValues() ? SMALLINT : TINYINT );
|
||||
|
||||
final JavaType<Integer> jdbcJavaType = javaTypeRegistry.getDescriptor( Integer.class );
|
||||
converter = new OrdinalEnumValueConverter<>( enumJavaType, jdbcType, jdbcJavaType );
|
||||
}
|
||||
else if ( style == EnumType.STRING ) {
|
||||
//noinspection rawtypes
|
||||
final JavaType jdbcJavaType;
|
||||
if ( jdbcTypeIndicators.getColumnLength() == 1 ) {
|
||||
jdbcJavaType = javaTypeRegistry.getDescriptor( Character.class );
|
||||
}
|
||||
else {
|
||||
jdbcJavaType = javaTypeRegistry.getDescriptor( String.class );
|
||||
}
|
||||
jdbcType = jdbcJavaType.getRecommendedJdbcType( jdbcTypeIndicators );
|
||||
//noinspection unchecked,rawtypes
|
||||
converter = new NamedEnumValueConverter<>( enumJavaType, jdbcType, jdbcJavaType );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( );
|
||||
}
|
||||
|
||||
return new EnumeratedValueResolution<>( jdbcType, converter, context );
|
||||
}
|
||||
|
||||
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.MetadataBuildingContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
|
@ -20,14 +21,12 @@ import org.hibernate.mapping.Table;
|
|||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.AdjustableBasicType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.SerializableType;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
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;
|
||||
|
@ -61,8 +60,10 @@ public class InferredBasicValueResolver {
|
|||
Selectable selectable,
|
||||
String ownerName,
|
||||
String propertyName,
|
||||
Dialect dialect,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
MetadataBuildingContext buildingContext) {
|
||||
final Dialect dialect = buildingContext.getMetadataCollector().getDatabase().getDialect();
|
||||
final TypeConfiguration typeConfiguration = buildingContext.getBootstrapContext().getTypeConfiguration();
|
||||
|
||||
final JavaType<T> reflectedJtd = reflectedJtdResolver.get();
|
||||
|
||||
// NOTE : the distinction that is made below wrt `explicitJavaType` and `reflectedJtd` is
|
||||
|
@ -79,7 +80,7 @@ public class InferredBasicValueResolver {
|
|||
null,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
buildingContext
|
||||
);
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( explicitJavaType ) ) {
|
||||
|
@ -131,7 +132,7 @@ public class InferredBasicValueResolver {
|
|||
null,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
buildingContext
|
||||
);
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( reflectedJtd ) ) {
|
||||
|
@ -162,14 +163,14 @@ public class InferredBasicValueResolver {
|
|||
final JavaType<?> elementJtd = containerJtd.getElementJavaType();
|
||||
final BasicType registeredElementType;
|
||||
if ( elementJtd instanceof EnumJavaType ) {
|
||||
final InferredBasicValueResolution resolution = InferredBasicValueResolver.fromEnum(
|
||||
(EnumJavaType) elementJtd,
|
||||
final EnumeratedValueResolution<?,?> resolution = fromEnum(
|
||||
(EnumJavaType<?>) elementJtd,
|
||||
null,
|
||||
null,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
buildingContext
|
||||
);
|
||||
registeredElementType = resolution.getLegacyResolvedBasicType();
|
||||
registeredElementType = resolution.getJdbcMapping();
|
||||
}
|
||||
else if ( JavaTypeHelper.isTemporal( elementJtd ) ) {
|
||||
final InferredBasicValueResolution resolution = InferredBasicValueResolver.fromTemporal(
|
||||
|
@ -321,60 +322,80 @@ public class InferredBasicValueResolver {
|
|||
}
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>, N extends Number> InferredBasicValueResolution<E,?> fromEnum(
|
||||
public static <E extends Enum<E>, R> EnumeratedValueResolution<E,R> fromEnum(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
BasicJavaType<R> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
final EnumType enumStyle = stdIndicators.getEnumeratedType();
|
||||
|
||||
if ( enumStyle == EnumType.STRING ) {
|
||||
//noinspection unchecked
|
||||
return (EnumeratedValueResolution<E, R>) stringEnumValueResolution(
|
||||
enumJavaType,
|
||||
explicitJavaType,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
if ( enumStyle == EnumType.ORDINAL ) {
|
||||
//noinspection unchecked
|
||||
return (EnumeratedValueResolution<E, R>) ordinalEnumValueResolution(
|
||||
enumJavaType,
|
||||
(BasicJavaType<? extends Number>)explicitJavaType,
|
||||
explicitJdbcType,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
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,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final EnumType enumStyle = stdIndicators.getEnumeratedType() != null
|
||||
? stdIndicators.getEnumeratedType()
|
||||
: EnumType.ORDINAL;
|
||||
MetadataBuildingContext context) {
|
||||
final JavaType<N> relationalJavaType = ordinalJavaType( explicitJavaType, context );
|
||||
final JdbcType jdbcType = ordinalJdbcType( explicitJdbcType, enumJavaType, context );
|
||||
|
||||
switch ( enumStyle ) {
|
||||
case STRING: {
|
||||
return stringEnumValueResolution(
|
||||
enumJavaType,
|
||||
explicitJavaType,
|
||||
explicitJdbcType,
|
||||
stdIndicators,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
case ORDINAL: {
|
||||
return ordinalEnumValueResolution(
|
||||
enumJavaType,
|
||||
explicitJavaType,
|
||||
explicitJdbcType,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
default: {
|
||||
throw new MappingException( "Unknown enumeration-style (JPA EnumType) : " + enumStyle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>, N extends Number> InferredBasicValueResolution<E,N> ordinalEnumValueResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
JavaType<N> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return ordinalResolution(
|
||||
enumJavaType,
|
||||
ordinalJavaType( explicitJavaType, typeConfiguration ),
|
||||
ordinalJdbcType( explicitJdbcType, enumJavaType, typeConfiguration ),
|
||||
typeConfiguration
|
||||
return new EnumeratedValueResolution<>(
|
||||
jdbcType,
|
||||
new OrdinalEnumValueConverter<>( enumJavaType, jdbcType, relationalJavaType ),
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
private static JdbcType ordinalJdbcType(JdbcType explicitJdbcType, EnumJavaType<?> enumJavaType, TypeConfiguration typeConfiguration) {
|
||||
private static JdbcType ordinalJdbcType(
|
||||
JdbcType explicitJdbcType,
|
||||
EnumJavaType<?> enumJavaType,
|
||||
MetadataBuildingContext context) {
|
||||
return explicitJdbcType != null
|
||||
? explicitJdbcType
|
||||
: typeConfiguration.getJdbcTypeRegistry().getDescriptor( enumJavaType.hasManyValues() ? SMALLINT : TINYINT );
|
||||
: context.getMetadataCollector().getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( enumJavaType.hasManyValues() ? SMALLINT : TINYINT );
|
||||
}
|
||||
|
||||
private static <N extends Number> JavaType<N> ordinalJavaType(JavaType<N> explicitJavaType, TypeConfiguration typeConfiguration) {
|
||||
private static <N extends Number> JavaType<N> ordinalJavaType(
|
||||
JavaType<N> explicitJavaType,
|
||||
MetadataBuildingContext context) {
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( !Integer.class.isAssignableFrom( explicitJavaType.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
|
@ -386,73 +407,25 @@ public class InferredBasicValueResolver {
|
|||
return explicitJavaType;
|
||||
}
|
||||
else {
|
||||
return typeConfiguration.getJavaTypeRegistry().getDescriptor( Integer.class );
|
||||
return context.getMetadataCollector().getTypeConfiguration().getJavaTypeRegistry().getDescriptor( Integer.class );
|
||||
}
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>, N extends Number> InferredBasicValueResolution<E, N> ordinalResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
JavaType<N> relationalJtd,
|
||||
JdbcType jdbcType,
|
||||
TypeConfiguration typeConfiguration
|
||||
) {
|
||||
final CustomType<E> customType = new CustomType<>(
|
||||
new org.hibernate.type.EnumType<>(
|
||||
enumJavaType.getJavaTypeClass(),
|
||||
new OrdinalEnumValueConverter<>( enumJavaType, jdbcType, relationalJtd ),
|
||||
typeConfiguration
|
||||
),
|
||||
typeConfiguration
|
||||
);
|
||||
return new InferredBasicValueResolution<>(
|
||||
customType,
|
||||
enumJavaType,
|
||||
relationalJtd,
|
||||
jdbcType,
|
||||
customType,
|
||||
ImmutableMutabilityPlan.instance()
|
||||
);
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> InferredBasicValueResolution<E, String> stringEnumValueResolution(
|
||||
private static <E extends Enum<E>> EnumeratedValueResolution<E,String> stringEnumValueResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
BasicJavaType<?> explicitJavaType,
|
||||
JdbcType explicitJdbcType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final JavaType<String> relationalJtd = stringJavaType( explicitJavaType, stdIndicators, typeConfiguration );
|
||||
return stringResolution(
|
||||
enumJavaType,
|
||||
relationalJtd,
|
||||
stringJdbcType( explicitJdbcType, stdIndicators, relationalJtd ),
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
MetadataBuildingContext context) {
|
||||
final JdbcType jdbcType = explicitJdbcType == null
|
||||
? enumJavaType.getRecommendedJdbcType( stdIndicators )
|
||||
: explicitJdbcType;
|
||||
final JavaType<String> relationalJtd = stringJavaType( explicitJavaType, stdIndicators, context );
|
||||
|
||||
private static <E extends Enum<E>> InferredBasicValueResolution<E, String> stringResolution(
|
||||
EnumJavaType<E> enumJavaType,
|
||||
JavaType<String> relationalJtd,
|
||||
JdbcType jdbcType,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final CustomType<E> customType = new CustomType<>(
|
||||
new org.hibernate.type.EnumType<>(
|
||||
enumJavaType.getJavaTypeClass(),
|
||||
new NamedEnumValueConverter<E>(
|
||||
enumJavaType,
|
||||
jdbcType,
|
||||
relationalJtd
|
||||
),
|
||||
typeConfiguration
|
||||
),
|
||||
typeConfiguration
|
||||
);
|
||||
return new InferredBasicValueResolution<>(
|
||||
customType,
|
||||
enumJavaType,
|
||||
relationalJtd,
|
||||
return new EnumeratedValueResolution<>(
|
||||
jdbcType,
|
||||
customType,
|
||||
ImmutableMutabilityPlan.instance()
|
||||
new NamedEnumValueConverter<>( enumJavaType, jdbcType, relationalJtd ),
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -462,7 +435,10 @@ public class InferredBasicValueResolver {
|
|||
: relationalJtd.getRecommendedJdbcType( stdIndicators );
|
||||
}
|
||||
|
||||
private static JavaType<String> stringJavaType(BasicJavaType<?> explicitJavaType, JdbcTypeIndicators stdIndicators, TypeConfiguration typeConfiguration) {
|
||||
private static JavaType<String> stringJavaType(
|
||||
BasicJavaType<?> explicitJavaType,
|
||||
JdbcTypeIndicators stdIndicators,
|
||||
MetadataBuildingContext context) {
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( ! String.class.isAssignableFrom( explicitJavaType.getJavaTypeClass() ) ) {
|
||||
throw new MappingException(
|
||||
|
@ -474,7 +450,7 @@ public class InferredBasicValueResolver {
|
|||
return (JavaType<String>) explicitJavaType;
|
||||
}
|
||||
else {
|
||||
return typeConfiguration.getJavaTypeRegistry()
|
||||
return context.getMetadataCollector().getTypeConfiguration().getJavaTypeRegistry()
|
||||
.getDescriptor( stdIndicators.getColumnLength() == 1 ? Character.class : String.class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,19 +112,22 @@ public class SqlStatementLogger {
|
|||
*/
|
||||
@AllowSysOut
|
||||
public void logStatement(String statement, Formatter formatter) {
|
||||
if ( logToStdout || LOG.isDebugEnabled() ) {
|
||||
try {
|
||||
if ( format ) {
|
||||
statement = formatter.format( statement );
|
||||
}
|
||||
if ( highlight ) {
|
||||
statement = FormatStyle.HIGHLIGHT.getFormatter().format( statement );
|
||||
}
|
||||
if ( !logToStdout && !LOG.isDebugEnabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if ( format ) {
|
||||
statement = formatter.format( statement );
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
LOG.warn( "Couldn't format statement", ex );
|
||||
if ( highlight ) {
|
||||
statement = FormatStyle.HIGHLIGHT.getFormatter().format( statement );
|
||||
}
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
LOG.warn( "Couldn't format statement", ex );
|
||||
}
|
||||
|
||||
LOG.debug( statement );
|
||||
if ( logToStdout ) {
|
||||
String prefix = highlight ? "\u001b[35m[Hibernate]\u001b[0m " : "Hibernate: ";
|
||||
|
|
|
@ -20,6 +20,7 @@ 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;
|
||||
|
@ -485,8 +486,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
column,
|
||||
ownerName,
|
||||
propertyName,
|
||||
getDialect(),
|
||||
getTypeConfiguration()
|
||||
getBuildingContext()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +569,6 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// Name could refer to:
|
||||
// 1) a named converter - HBM support for JPA's AttributeConverter via its `type="..."` XML attribute
|
||||
// 2) a "named composed" mapping - like (1), this is mainly to support envers since it tells
|
||||
|
@ -589,6 +588,10 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
);
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
|
|
|
@ -67,10 +67,6 @@ public interface JdbcMapping extends MappingType, JdbcMappingContainer {
|
|||
*/
|
||||
JdbcType getJdbcType();
|
||||
|
||||
default CastType getCastType() {
|
||||
return getJdbcType().getCastType();
|
||||
}
|
||||
|
||||
/**
|
||||
* The strategy for extracting values of this expressible
|
||||
* type from JDBC ResultSets, CallableStatements, etc
|
||||
|
@ -83,6 +79,10 @@ public interface JdbcMapping extends MappingType, JdbcMappingContainer {
|
|||
*/
|
||||
ValueBinder getJdbcValueBinder();
|
||||
|
||||
default CastType getCastType() {
|
||||
return getJdbcType().getCastType();
|
||||
}
|
||||
|
||||
/**
|
||||
* The strategy for formatting values of this expressible type to
|
||||
* a SQL literal.
|
||||
|
|
|
@ -17,8 +17,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
|
@ -47,11 +45,11 @@ import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
|||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.DynamicModelJavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.EntityJavaType;
|
||||
|
@ -584,40 +582,27 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
final Consumer<PersistentAttribute<?, ?>> attributeConsumer = persistentAttribute -> {
|
||||
if ( persistentAttribute.getJavaType() != null && persistentAttribute.getJavaType().isEnum() ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<Enum<?>> enumClass = (Class<Enum<?>>) persistentAttribute.getJavaType();
|
||||
final Enum<?>[] enumConstants = enumClass.getEnumConstants();
|
||||
typeConfiguration.getJavaTypeRegistry().forEachDescriptor( (descriptor) -> {
|
||||
if ( descriptor instanceof EnumJavaType ) {
|
||||
final EnumJavaType<? extends Enum<?>> enumJavaType = (EnumJavaType<? extends Enum<?>>) descriptor;
|
||||
final Class<? extends Enum<?>> enumJavaClass = enumJavaType.getJavaTypeClass();
|
||||
final Enum<?>[] enumConstants = enumJavaClass.getEnumConstants();
|
||||
for ( Enum<?> enumConstant : enumConstants ) {
|
||||
final String qualifiedEnumLiteral = enumConstant.getDeclaringClass()
|
||||
.getSimpleName() + "." + enumConstant.name();
|
||||
allowedEnumLiteralTexts
|
||||
.computeIfAbsent( enumConstant.name(), (s) -> new HashMap<>() )
|
||||
.put( enumJavaClass, enumConstant );
|
||||
|
||||
this.allowedEnumLiteralTexts.computeIfAbsent(
|
||||
enumConstant.name(),
|
||||
k -> new HashMap<>()
|
||||
).put( enumClass, enumConstant );
|
||||
this.allowedEnumLiteralTexts.computeIfAbsent(
|
||||
qualifiedEnumLiteral,
|
||||
k -> new HashMap<>()
|
||||
).put( enumClass, enumConstant );
|
||||
final String simpleQualifiedName = enumJavaClass.getSimpleName() + "." + enumConstant.name();
|
||||
allowedEnumLiteralTexts
|
||||
.computeIfAbsent( simpleQualifiedName, (s) -> new HashMap<>() )
|
||||
.put( enumJavaClass, enumConstant );
|
||||
}
|
||||
}
|
||||
};
|
||||
domainTypeStream( context ).forEach(
|
||||
managedDomainType -> managedDomainType.visitAttributes( attributeConsumer )
|
||||
);
|
||||
} );
|
||||
|
||||
applyNamedEntityGraphs( namedEntityGraphDefinitions );
|
||||
}
|
||||
|
||||
private static Stream<ManagedDomainType<?>> domainTypeStream(MetadataContext context) {
|
||||
return Stream.concat(
|
||||
context.getIdentifiableTypesByName().values().stream(),
|
||||
context.getEmbeddableTypeSet().stream()
|
||||
);
|
||||
}
|
||||
|
||||
private EntityDomainType<?> locateOrBuildEntityType(
|
||||
PersistentClass persistentClass,
|
||||
MetadataContext context,
|
||||
|
|
|
@ -49,7 +49,10 @@ import org.jboss.logging.Logger;
|
|||
* @author Emmanuel Bernard
|
||||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Use {@link ConvertedBasicType} instead
|
||||
*/
|
||||
@Deprecated(since="6.2", forRemoval=true)
|
||||
public class EnumType<T extends Enum<T>>
|
||||
implements EnhancedUserType<T>, DynamicParameterizedType, LoggableUserType, TypeConfigurationAware, Serializable {
|
||||
private static final Logger LOG = CoreLogging.logger( EnumType.class );
|
||||
|
|
|
@ -13,6 +13,11 @@ import java.sql.SQLException;
|
|||
/**
|
||||
* Contract for binding values to a JDBC {@link PreparedStatement}.
|
||||
*
|
||||
* @apiNote Binders, as well as {@linkplain ValueExtractor extractors}, should never apply
|
||||
* {@linkplain org.hibernate.type.descriptor.converter.spi.BasicValueConverter conversions}.
|
||||
* Instead, callers of the binder are expected to coordinate between the binding and
|
||||
* conversion.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ValueBinder<X> {
|
||||
|
|
|
@ -14,6 +14,11 @@ import java.sql.SQLException;
|
|||
* Contract for extracting values from a JDBC {@link ResultSet} or
|
||||
* from output the parameters of a {@link CallableStatement}.
|
||||
*
|
||||
* @apiNote Extractors, as well as {@linkplain ValueBinder binders}, should never apply
|
||||
* {@linkplain org.hibernate.type.descriptor.converter.spi.BasicValueConverter conversions}.
|
||||
* Instead, callers of the extractor are expected to coordinate between the extraction and
|
||||
* conversion.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ValueExtractor<X> {
|
||||
|
|
|
@ -37,9 +37,10 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
final JdbcTypeRegistry registry = context.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
final EnumType type = context.getEnumeratedType();
|
||||
switch ( type == null ? ORDINAL : type ) {
|
||||
case ORDINAL:
|
||||
case ORDINAL: {
|
||||
return registry.getDescriptor( hasManyValues() ? SMALLINT : TINYINT );
|
||||
case STRING:
|
||||
}
|
||||
case STRING: {
|
||||
if ( context.getColumnLength() == 1 ) {
|
||||
return context.isNationalized()
|
||||
? registry.getDescriptor( NCHAR )
|
||||
|
@ -48,8 +49,10 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
return context.isNationalized()
|
||||
? registry.getDescriptor( NVARCHAR )
|
||||
: registry.getDescriptor( VARCHAR );
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure("unknown EnumType");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.io.Serializable;
|
|||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.type.descriptor.java.ArrayJavaType;
|
||||
|
@ -70,35 +71,12 @@ public class JavaTypeRegistry implements JavaTypeBaseline.BaselineTarget, Serial
|
|||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// descriptor access
|
||||
|
||||
public void forEachDescriptor(Consumer<JavaType<?>> consumer) {
|
||||
descriptorsByType.values().forEach( consumer );
|
||||
}
|
||||
|
||||
public <T> JavaType<T> getDescriptor(Type javaType) {
|
||||
return resolveDescriptor( javaType );
|
||||
// return RegistryHelper.INSTANCE.resolveDescriptor(
|
||||
// descriptorsByClass,
|
||||
// javaType,
|
||||
// () -> {
|
||||
// log.debugf(
|
||||
// "Could not find matching scoped JavaType for requested Java class [%s]; " +
|
||||
// "falling back to static registry",
|
||||
// javaType.getName()
|
||||
// );
|
||||
//
|
||||
// if ( Serializable.class.isAssignableFrom( javaType ) ) {
|
||||
// return new SerializableTypeDescriptor( javaType );
|
||||
// }
|
||||
//
|
||||
// if ( !AttributeConverter.class.isAssignableFrom( javaType ) ) {
|
||||
// log.debugf(
|
||||
// "Could not find matching JavaType for requested Java class [%s]; using fallback. " +
|
||||
// "This means Hibernate does not know how to perform certain basic operations in relation to this Java type." +
|
||||
// "",
|
||||
// javaType.getName()
|
||||
// );
|
||||
// checkEqualsAndHashCode( javaType );
|
||||
// }
|
||||
//
|
||||
// return new FallbackJavaType<>( javaType );
|
||||
// }
|
||||
// );
|
||||
}
|
||||
|
||||
public void addDescriptor(JavaType<?> descriptor) {
|
||||
|
@ -115,6 +93,7 @@ public class JavaTypeRegistry implements JavaTypeBaseline.BaselineTarget, Serial
|
|||
}
|
||||
|
||||
public <J> JavaType<J> findDescriptor(Type javaType) {
|
||||
//noinspection unchecked
|
||||
return (JavaType<J>) descriptorsByType.get( javaType );
|
||||
}
|
||||
|
||||
|
@ -200,25 +179,19 @@ public class JavaTypeRegistry implements JavaTypeBaseline.BaselineTarget, Serial
|
|||
final ParameterizedType parameterizedType = (ParameterizedType) javaType;
|
||||
javaTypeClass = (Class<J>) parameterizedType.getRawType();
|
||||
}
|
||||
final MutabilityPlan<J> mutabilityPlan;
|
||||
|
||||
final MutabilityPlan<J> determinedPlan = RegistryHelper.INSTANCE.determineMutabilityPlan(
|
||||
javaType,
|
||||
typeConfiguration
|
||||
);
|
||||
if ( determinedPlan != null ) {
|
||||
mutabilityPlan = determinedPlan;
|
||||
}
|
||||
else {
|
||||
mutabilityPlan = (MutabilityPlan<J>) MutableMutabilityPlan.INSTANCE;
|
||||
}
|
||||
return entity ? new EntityJavaType<>( javaTypeClass, mutabilityPlan )
|
||||
final MutabilityPlan<J> mutabilityPlan = (determinedPlan != null)
|
||||
? determinedPlan
|
||||
: (MutabilityPlan<J>) MutableMutabilityPlan.INSTANCE;
|
||||
|
||||
return entity
|
||||
? new EntityJavaType<>( javaTypeClass, mutabilityPlan )
|
||||
: new JavaTypeBasicAdaptor<>( javaTypeClass, mutabilityPlan );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public JavaType<?> resolveDynamicEntityDescriptor(String typeName) {
|
||||
return new DynamicModelJavaType();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.hibernate.mapping.PersistentClass;
|
|||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -56,8 +55,7 @@ public class NestedEmbeddableMetadataTest {
|
|||
assertEquals( (Long) 500L, selectable.getLength() );
|
||||
Component amountMetadata = (Component) investmentMetadata.getProperty( "amount" ).getValue();
|
||||
SimpleValue currencyMetadata = (SimpleValue) amountMetadata.getProperty( "currency" ).getValue();
|
||||
CustomType<Object> currencyType = (CustomType<Object>) currencyMetadata.getType();
|
||||
int[] currencySqlTypes = currencyType.getSqlTypeCodes( metadata );
|
||||
int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata );
|
||||
assertEquals( 1, currencySqlTypes.length );
|
||||
assertJdbcTypeCode(
|
||||
typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARCHAR ).getJdbcTypeCode(),
|
||||
|
|
|
@ -19,11 +19,8 @@ import org.hibernate.mapping.PersistentClass;
|
|||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertJdbcTypeCode;
|
||||
|
@ -54,8 +51,7 @@ public class FieldAccessedNestedEmbeddableMetadataTest {
|
|||
assertEquals( (Long) 500L, selectable.getLength() );
|
||||
Component amountMetadata = (Component) investmentMetadata.getProperty( "amount" ).getValue();
|
||||
SimpleValue currencyMetadata = (SimpleValue) amountMetadata.getProperty( "currency" ).getValue();
|
||||
CustomType<Object> currencyType = (CustomType<Object>) currencyMetadata.getType();
|
||||
int[] currencySqlTypes = currencyType.getSqlTypeCodes( metadata );
|
||||
int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata );
|
||||
assertEquals( 1, currencySqlTypes.length );
|
||||
assertJdbcTypeCode(
|
||||
typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARCHAR ).getJdbcTypeCode(),
|
||||
|
|
|
@ -7,25 +7,30 @@
|
|||
package org.hibernate.orm.test.annotations.enumerated;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.assertj.core.api.Assert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
|
@ -34,29 +39,16 @@ import static org.junit.Assert.assertThat;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EnumeratedSmokeTest extends BaseUnitTestCase {
|
||||
private StandardServiceRegistry ssr;
|
||||
|
||||
@Before
|
||||
public void prepare() {
|
||||
ssr = new StandardServiceRegistryBuilder().build();
|
||||
}
|
||||
|
||||
@After
|
||||
public void release() {
|
||||
if ( ssr != null ) {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceRegistry
|
||||
public class EnumeratedSmokeTest {
|
||||
/**
|
||||
* I personally have been unable to repeoduce the bug as reported in HHH-10402. This test
|
||||
* is equivalent to what the reporters say happens, but these tests pass fine.
|
||||
*/
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10402" )
|
||||
public void testEnumeratedTypeResolutions() {
|
||||
final MetadataImplementor mappings = (MetadataImplementor) new MetadataSources( ssr )
|
||||
@JiraKey( "HHH-10402" )
|
||||
public void testEnumeratedTypeResolutions(ServiceRegistryScope serviceRegistryScope) {
|
||||
final MetadataImplementor mappings = (MetadataImplementor) new MetadataSources( serviceRegistryScope.getRegistry() )
|
||||
.addAnnotatedClass( EntityWithEnumeratedAttributes.class )
|
||||
.buildMetadata();
|
||||
mappings.orderColumns( false );
|
||||
|
@ -72,20 +64,20 @@ public class EnumeratedSmokeTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
private void validateEnumMapping(JdbcTypeRegistry jdbcRegistry, Property property, EnumType expectedJpaEnumType) {
|
||||
assertThat( property.getType(), instanceOf( CustomType.class ) );
|
||||
final CustomType<Object> customType = (CustomType<Object>) property.getType();
|
||||
assertThat( customType.getUserType(), instanceOf( org.hibernate.type.EnumType.class ) );
|
||||
final org.hibernate.type.EnumType hibernateMappingEnumType = (org.hibernate.type.EnumType) customType.getUserType();
|
||||
assertThat( hibernateMappingEnumType.isOrdinal(), is(expectedJpaEnumType==EnumType.ORDINAL) );
|
||||
final int expectedJdbcTypeCode = jdbcRegistry.getDescriptor(
|
||||
expectedJpaEnumType == EnumType.ORDINAL ?
|
||||
Types.TINYINT :
|
||||
Types.VARCHAR
|
||||
).getJdbcTypeCode();
|
||||
assertThat(
|
||||
hibernateMappingEnumType.getSqlType(),
|
||||
is( expectedJdbcTypeCode )
|
||||
);
|
||||
final ConvertedBasicType<?> propertyType = (ConvertedBasicType<?>) property.getType();
|
||||
final EnumValueConverter<?, ?> valueConverter = (EnumValueConverter<?, ?>) propertyType.getValueConverter();
|
||||
final JdbcMapping jdbcMapping = propertyType.getJdbcMapping();
|
||||
final JdbcType jdbcType = jdbcMapping.getJdbcType();
|
||||
|
||||
assert expectedJpaEnumType != null;
|
||||
if ( expectedJpaEnumType == EnumType.ORDINAL ) {
|
||||
Assertions.assertThat( valueConverter ).isInstanceOf( OrdinalEnumValueConverter.class );
|
||||
Assertions.assertThat( jdbcType.isInteger() ).isTrue();
|
||||
}
|
||||
else {
|
||||
Assertions.assertThat( valueConverter ).isInstanceOf( NamedEnumValueConverter.class );
|
||||
Assertions.assertThat( jdbcType.isString() ).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
|
||||
|
@ -73,19 +74,17 @@ public class EnumeratedWithMappedSuperclassTest extends BaseUnitTestCase {
|
|||
final PersistentClass addressLevelBinding = metadata.getEntityBinding( AddressLevel.class.getName() );
|
||||
|
||||
final Property natureProperty = addressLevelBinding.getProperty( "nature" );
|
||||
CustomType<Object> customType = assertTyping( CustomType.class, natureProperty.getType() );
|
||||
EnumType enumType = assertTyping( EnumType.class, customType.getUserType() );
|
||||
assertEquals( Types.VARCHAR, enumType.getSqlType() );
|
||||
//noinspection unchecked
|
||||
ConvertedBasicType<Nature> natureMapping = (ConvertedBasicType<Nature>) natureProperty.getType();
|
||||
assertEquals( Types.VARCHAR, natureMapping.getJdbcType().getJdbcTypeCode() );
|
||||
|
||||
SessionFactoryImplementor sf = (SessionFactoryImplementor) metadata.buildSessionFactory();
|
||||
try {
|
||||
EntityPersister p = sf.getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(AddressLevel.class.getName());
|
||||
CustomType<Object> runtimeType = assertTyping( CustomType.class, p.getPropertyType( "nature" ) );
|
||||
EnumType runtimeEnumType = assertTyping( EnumType.class, runtimeType.getUserType() );
|
||||
assertEquals( Types.VARCHAR, runtimeEnumType.getSqlType() );
|
||||
}
|
||||
finally {
|
||||
sf.close();
|
||||
try ( SessionFactoryImplementor sf = (SessionFactoryImplementor) metadata.buildSessionFactory() ) {
|
||||
EntityPersister p = sf.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.getEntityDescriptor( AddressLevel.class.getName() );
|
||||
//noinspection unchecked
|
||||
ConvertedBasicType<Nature> runtimeType = (ConvertedBasicType<Nature>) p.getPropertyType( "nature" );
|
||||
assertEquals( Types.VARCHAR, runtimeType.getJdbcType().getJdbcTypeCode() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.annotations.enumerated.ormXml;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -19,6 +22,7 @@ import org.hibernate.testing.junit4.BaseUnitTestCase;
|
|||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
|
@ -39,9 +43,9 @@ public class OrmXmlEnumTypeTest extends BaseUnitTestCase {
|
|||
Type bindingPropertyType = metadata.getEntityBinding( BookWithOrmEnum.class.getName() )
|
||||
.getProperty( "bindingStringEnum" )
|
||||
.getType();
|
||||
CustomType<Object> customType = ExtraAssertions.assertTyping( CustomType.class, bindingPropertyType );
|
||||
EnumType enumType = ExtraAssertions.assertTyping( EnumType.class, customType.getUserType() );
|
||||
assertFalse( enumType.isOrdinal() );
|
||||
|
||||
ConvertedBasicType<?> enumMapping = ExtraAssertions.assertTyping( ConvertedBasicType.class, bindingPropertyType );
|
||||
assertEquals( Types.VARCHAR, enumMapping.getJdbcType().getJdbcTypeCode() );
|
||||
}
|
||||
finally {
|
||||
ServiceRegistryBuilder.destroy( ssr );
|
||||
|
|
|
@ -8,12 +8,6 @@ package org.hibernate.orm.test.bootstrap.binding.annotations.basics;
|
|||
|
||||
import java.sql.Types;
|
||||
import java.util.function.Consumer;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
|
@ -24,19 +18,23 @@ import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
|||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.JpaAttributeConverter;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.internal.ConvertedBasicTypeImpl;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
import static jakarta.persistence.EnumType.ORDINAL;
|
||||
import static jakarta.persistence.EnumType.STRING;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
@ -128,9 +126,6 @@ public class EnumResolutionTests {
|
|||
//noinspection rawtypes
|
||||
final Class converterType = ( (JpaAttributeConverter) converter ).getConverterBean().getBeanClass();
|
||||
assertThat( converterType, equalTo( ConverterImpl.class ) );
|
||||
},
|
||||
(legacyResolution) -> {
|
||||
assertThat( legacyResolution, instanceOf( ConvertedBasicTypeImpl.class ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -150,6 +145,22 @@ public class EnumResolutionTests {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleCharEnumResolution(DomainModelScope scope) {
|
||||
final PersistentClass entityBinding = scope
|
||||
.getDomainModel()
|
||||
.getEntityBinding( EntityWithEnums.class.getName() );
|
||||
|
||||
verifyEnumResolution(
|
||||
entityBinding.getProperty( "singleCharEnum" ),
|
||||
Types.CHAR,
|
||||
Character.class,
|
||||
(converter) -> {
|
||||
Assertions.assertThat( converter.getRelationalJavaType().getJavaTypeClass() ).isEqualTo( Character.class );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void verifyEnumResolution(
|
||||
Property property,
|
||||
|
@ -164,13 +175,6 @@ public class EnumResolutionTests {
|
|||
valueConverter -> {
|
||||
assertThat( valueConverter, notNullValue() );
|
||||
assertThat( valueConverter, instanceOf( converterClass ) );
|
||||
},
|
||||
legacyResolvedType -> {
|
||||
assertThat( legacyResolvedType, instanceOf( CustomType.class ) );
|
||||
final UserType rawEnumUserType = ( (CustomType<Object>) legacyResolvedType ).getUserType();
|
||||
assertThat( rawEnumUserType, instanceOf( EnumType.class ) );
|
||||
final EnumType rawEnumEnumType = (EnumType) rawEnumUserType;
|
||||
assertThat( rawEnumEnumType.isOrdinal(), is( isOrdinal ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -180,11 +184,11 @@ public class EnumResolutionTests {
|
|||
Property property,
|
||||
int jdbcCode,
|
||||
Class<?> javaType,
|
||||
Consumer<BasicValueConverter> converterChecker,
|
||||
Consumer<BasicType> legacyTypeChecker) {
|
||||
Consumer<BasicValueConverter> converterChecker) {
|
||||
final BasicValue.Resolution<?> resolution = ( (BasicValue) property.getValue() ).resolve();
|
||||
final TypeConfiguration typeConfiguration = ( (BasicValue) property.getValue() ).getTypeConfiguration();
|
||||
final JdbcType jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( jdbcCode );
|
||||
|
||||
// verify the interpretations used for reading
|
||||
assertThat( resolution.getJdbcType(), is( jdbcType ) );
|
||||
assertThat( resolution.getRelationalJavaType().getJavaTypeClass(), equalTo( javaType ) );
|
||||
|
@ -195,9 +199,6 @@ public class EnumResolutionTests {
|
|||
assertThat( jdbcMapping.getJdbcJavaType(), equalTo( resolution.getRelationalJavaType() ) );
|
||||
|
||||
converterChecker.accept( resolution.getValueConverter() );
|
||||
|
||||
// verify the (legacy) interpretations used for writing
|
||||
legacyTypeChecker.accept( resolution.getLegacyResolvedBasicType() );
|
||||
}
|
||||
|
||||
@Entity( name = "EntityWithEnums" )
|
||||
|
@ -224,6 +225,10 @@ public class EnumResolutionTests {
|
|||
@Enumerated( ORDINAL )
|
||||
@JdbcTypeCode( Types.SMALLINT )
|
||||
private Values explicitEnum;
|
||||
|
||||
@Enumerated( STRING )
|
||||
@Column( length = 1 )
|
||||
private Values singleCharEnum;
|
||||
}
|
||||
|
||||
enum Values { FIRST, SECOND }
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.bootstrap.spi.delegation;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.spi.AbstractDelegatingMetadata;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
|
||||
/**
|
||||
* If this class does not compile anymore due to unimplemented methods, you should probably add the corresponding
|
||||
|
|
|
@ -25,14 +25,13 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
|||
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.EnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.JpaAttributeConverter;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
|
@ -92,9 +91,8 @@ public class SmokeTests {
|
|||
|
||||
assertThat( genderAttrMapping.getJavaType().getJavaTypeClass(), equalTo( Gender.class ) );
|
||||
|
||||
final CustomType<?> basicType = (CustomType<?>) genderAttrMapping.getJdbcMapping();
|
||||
final org.hibernate.type.EnumType<?> enumType = (org.hibernate.type.EnumType<?>) basicType.getUserType();
|
||||
final EnumValueConverter<?, ?> valueConverter = enumType.getEnumValueConverter();
|
||||
final ConvertedBasicType<?> jdbcMapping = (ConvertedBasicType<?>) genderAttrMapping.getJdbcMapping();
|
||||
final EnumValueConverter<?, ?> valueConverter = (EnumValueConverter<?, ?>) jdbcMapping.getValueConverter();
|
||||
assertThat( valueConverter, instanceOf( OrdinalEnumValueConverter.class ) );
|
||||
assertThat(
|
||||
valueConverter.getDomainJavaType().getJavaTypeClass(),
|
||||
|
@ -117,9 +115,8 @@ public class SmokeTests {
|
|||
|
||||
assertThat( attrMapping.getJavaType().getJavaTypeClass(), equalTo( Gender.class ) );
|
||||
|
||||
final CustomType<?> basicType = (CustomType<?>) attrMapping.getJdbcMapping();
|
||||
final org.hibernate.type.EnumType<?> enumType = (org.hibernate.type.EnumType<?>) basicType.getUserType();
|
||||
final EnumValueConverter<?, ?> valueConverter = enumType.getEnumValueConverter();
|
||||
final ConvertedBasicType<?> jdbcMapping = (ConvertedBasicType<?>) attrMapping.getJdbcMapping();
|
||||
final EnumValueConverter<?, ?> valueConverter = (EnumValueConverter<?, ?>) jdbcMapping.getValueConverter();
|
||||
assertThat( valueConverter, instanceOf( NamedEnumValueConverter.class ) );
|
||||
assertThat(
|
||||
valueConverter.getDomainJavaType().getJavaTypeClass(),
|
||||
|
@ -142,7 +139,7 @@ public class SmokeTests {
|
|||
|
||||
assertThat( attrMapping.getJavaType().getJavaTypeClass(), equalTo( Gender.class ) );
|
||||
|
||||
final BasicValueConverter valueConverter = ( (BasicType<?>) attrMapping.getJdbcMapping() ).getValueConverter();
|
||||
final BasicValueConverter<?,?> valueConverter = ( (ConvertedBasicType<?>) attrMapping.getJdbcMapping() ).getValueConverter();
|
||||
assertThat( valueConverter, instanceOf( JpaAttributeConverter.class ) );
|
||||
assertThat( valueConverter.getDomainJavaType(), is( attrMapping.getJavaType() ) );
|
||||
assertThat( valueConverter.getRelationalJavaType().getJavaTypeClass(), equalTo( Character.class ) );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.orm.test.sql.ast;
|
|||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||
import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
|
@ -39,6 +40,7 @@ import org.hibernate.sql.results.graph.basic.BasicResultAssembler;
|
|||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import org.hibernate.testing.hamcrest.AssignableMatcher;
|
||||
|
@ -117,9 +119,6 @@ public class SmokeTests {
|
|||
public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = session.getFactory()
|
||||
.getTypeConfiguration()
|
||||
.getJdbcTypeRegistry();
|
||||
final QueryImplementor<Gender> query = session.createQuery( "select e.gender from SimpleEntity e", Gender.class );
|
||||
final SqmQueryImplementor<Gender> hqlQuery = (SqmQueryImplementor<Gender>) query;
|
||||
final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
|
||||
|
@ -167,17 +166,11 @@ public class SmokeTests {
|
|||
final ColumnReference columnReference = (ColumnReference) selectedExpression;
|
||||
assertThat( columnReference.getExpressionText(), is( "s1_0.gender" ) );
|
||||
|
||||
final JdbcMappingContainer selectedExpressible = selectedExpression.getExpressionType();
|
||||
assertThat( selectedExpressible, instanceOf( CustomType.class ) );
|
||||
final CustomType<?> basicType = (CustomType<?>) selectedExpressible;
|
||||
final EnumType<?> enumType = (EnumType<?>) basicType.getUserType();
|
||||
final EnumValueConverter<?, ?> enumConverter = enumType.getEnumValueConverter();
|
||||
assertThat( enumConverter.getRelationalJavaType().getJavaTypeClass(), AssignableMatcher.assignableTo( Integer.class ) );
|
||||
assertThat(
|
||||
basicType.getJdbcType(),
|
||||
is( jdbcTypeRegistry.getDescriptor( Types.TINYINT ) )
|
||||
);
|
||||
final JdbcMapping selectedExpressible = selectedExpression.getExpressionType().getSingleJdbcMapping();
|
||||
assertThat( selectedExpressible.getJdbcType().isInteger(), is( true ) );
|
||||
|
||||
final EnumValueConverter<?, ?> enumConverter = (EnumValueConverter<?, ?>) selectedExpressible.getValueConverter();
|
||||
assertThat( enumConverter.getRelationalJavaType().getJavaTypeClass(), AssignableMatcher.assignableTo( Integer.class ) );
|
||||
|
||||
assertThat( sqlAst.getDomainResultDescriptors().size(), is( 1 ) );
|
||||
final DomainResult<?> domainResult = sqlAst.getDomainResultDescriptors().get( 0 );
|
||||
|
|
|
@ -41,6 +41,7 @@ import static org.junit.Assert.assertThat;
|
|||
* @author Christian Beikov
|
||||
*/
|
||||
@SkipForDialect(value = SybaseASEDialect.class, comment = "Sybase or the driver are trimming trailing zeros in byte arrays")
|
||||
@SkipForDialect( value = OracleDialect.class, jiraKey = "HHH-16333", comment = "converters not handled properly" )
|
||||
public class EnumArrayTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,9 +16,13 @@ import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder;
|
|||
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;
|
||||
|
||||
/**
|
||||
* Generates metadata for basic properties: immutable types (including enums).
|
||||
|
@ -71,7 +75,10 @@ public final class BasicMetadataGenerator {
|
|||
typeDefinition.setParameter( EnumType.NAMED, parameters.getProperty( EnumType.NAMED ) );
|
||||
}
|
||||
else {
|
||||
typeDefinition.setParameter( EnumType.NAMED, "" + !( (EnumType) ( (CustomType<Object>) type ).getUserType() ).isOrdinal() );
|
||||
final ConvertedBasicType<?> convertedType = (ConvertedBasicType<?>) type;
|
||||
final EnumValueConverter<?, ?> valueConverter = (EnumValueConverter<?, ?>) convertedType.getValueConverter();
|
||||
final boolean isNamed = valueConverter instanceof NamedEnumValueConverter;
|
||||
typeDefinition.setParameter( EnumType.NAMED, Boolean.toString( isNamed ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,15 +133,10 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
private boolean isEnumType(Type type, String typeName) {
|
||||
// Check if a custom type implementation is used and it extends the EnumType directly.
|
||||
if ( type instanceof CustomType ) {
|
||||
final CustomType<?> customType = (CustomType<?>) type;
|
||||
if ( customType.getUserType() instanceof EnumType ) {
|
||||
return true;
|
||||
}
|
||||
if ( type instanceof ConvertedBasicType ) {
|
||||
final ConvertedBasicType<?> convertedType = (ConvertedBasicType<?>) type;
|
||||
return convertedType.getValueConverter() instanceof EnumValueConverter;
|
||||
}
|
||||
|
||||
// Check if it is an EnumType without a custom type
|
||||
return EnumType.class.getName().equals( typeName );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.envers.entities.customtype;
|
||||
|
||||
import jakarta.persistence.ColumnResult;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.SqlResultSetMapping;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
|
@ -19,6 +21,13 @@ import org.hibernate.envers.Audited;
|
|||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
@SqlResultSetMapping(
|
||||
name = "e1_e2",
|
||||
columns = {
|
||||
@ColumnResult( name = "enum1", type = String.class ),
|
||||
@ColumnResult( name = "enum2", type = Integer.class )
|
||||
}
|
||||
)
|
||||
public class EnumTypeEntity {
|
||||
public static enum E1 {X, Y}
|
||||
|
||||
|
|
|
@ -9,18 +9,35 @@ package org.hibernate.orm.test.envers.integration.collection;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedCollectionPart;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.orm.test.envers.Priority;
|
||||
import org.hibernate.orm.test.envers.entities.collection.EnumSetEntity;
|
||||
import org.hibernate.orm.test.envers.entities.collection.EnumSetEntity.E1;
|
||||
import org.hibernate.orm.test.envers.entities.collection.EnumSetEntity.E2;
|
||||
import org.hibernate.orm.test.envers.tools.TestTools;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.ConvertedBasicType;
|
||||
import org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
|
@ -98,19 +115,48 @@ public class EnumSet extends BaseEnversJPAFunctionalTestCase {
|
|||
@TestForIssue(jiraKey = "HHH-7780")
|
||||
public void testEnumRepresentation() {
|
||||
EntityManager entityManager = getEntityManager();
|
||||
List<Object> enums1 = entityManager.createNativeQuery(
|
||||
"SELECT enums1 FROM EnumSetEntity_enums1_AUD ORDER BY REV ASC"
|
||||
).getResultList();
|
||||
List<Object> enums2 = entityManager.createNativeQuery(
|
||||
"SELECT enums2 FROM EnumSetEntity_enums2_AUD ORDER BY REV ASC"
|
||||
).getResultList();
|
||||
|
||||
verifyModel( entityManager );
|
||||
|
||||
{
|
||||
final String qry = "SELECT enums1 FROM EnumSetEntity_enums1_AUD ORDER BY REV ASC";
|
||||
List<String> enums1 = entityManager.createNativeQuery( qry, String.class ).getResultList();
|
||||
Assertions.assertThat( enums1 ).isEqualTo( List.of( "X", "Y", "X" ) );
|
||||
}
|
||||
|
||||
{
|
||||
final String qry = "SELECT enums2 FROM EnumSetEntity_enums2_AUD ORDER BY REV ASC";
|
||||
String enum2 = (String) entityManager.createNativeQuery( qry, String.class ).getSingleResult();
|
||||
// Compare the String value to account for, as an example, Oracle returning a BigDecimal instead of an int.
|
||||
Assertions.assertThat( enum2 ).isEqualTo( "0" );
|
||||
}
|
||||
|
||||
entityManager.close();
|
||||
}
|
||||
|
||||
Assert.assertEquals( Arrays.asList( "X", "Y", "X" ), enums1 );
|
||||
private void verifyModel(EntityManager entityManager) {
|
||||
final MappingMetamodelImplementor mappingMetamodel = entityManager.unwrap( SessionImplementor.class )
|
||||
.getFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getMappingMetamodel();
|
||||
|
||||
Assert.assertEquals( 1, enums2.size() );
|
||||
Object enum2 = enums2.get( 0 );
|
||||
// Compare the Strings to account for, as an example, Oracle returning a BigDecimal instead of an int.
|
||||
Assert.assertEquals( "0", enum2.toString() );
|
||||
{
|
||||
final EntityMappingType entityMapping = mappingMetamodel.getEntityDescriptor( EnumSetEntity.class );
|
||||
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) entityMapping.findDeclaredAttributeMapping( "enums1" );
|
||||
verifyMapping( attributeMapping.getElementDescriptor().getJdbcMapping( 0 ) );
|
||||
}
|
||||
|
||||
{
|
||||
final EntityMappingType entityMapping = mappingMetamodel.getEntityDescriptor( "EnumSetEntity_enums1_AUD" );
|
||||
final CompositeIdentifierMapping cidMapping = (CompositeIdentifierMapping) entityMapping.getIdentifierMapping();
|
||||
verifyMapping( cidMapping.getEmbeddableTypeDescriptor().findAttributeMapping( "element" ).getJdbcMapping( 0 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void verifyMapping(JdbcMapping jdbcMapping) {
|
||||
final ConvertedBasicType<?> convertedBasicType = (ConvertedBasicType<?>) jdbcMapping;
|
||||
assertThat( convertedBasicType.getValueConverter() ).isInstanceOf( NamedEnumValueConverter.class );
|
||||
assertThat( convertedBasicType.getValueConverter().getRelationalJavaType().getJavaTypeClass() ).isEqualTo( String.class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.envers.integration.customtype;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.orm.test.envers.Priority;
|
||||
import org.hibernate.orm.test.envers.entities.customtype.EnumTypeEntity;
|
||||
|
@ -17,6 +14,8 @@ import org.hibernate.testing.TestForIssue;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
|
@ -44,15 +43,13 @@ public class EnumTypeTest extends BaseEnversJPAFunctionalTestCase {
|
|||
public void testEnumRepresentation() {
|
||||
EntityManager entityManager = getEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
List<Object[]> values = entityManager.createNativeQuery(
|
||||
"SELECT enum1, enum2 FROM EnumTypeEntity_AUD ORDER BY REV ASC"
|
||||
).getResultList();
|
||||
|
||||
final String qry = "SELECT enum1, enum2 FROM EnumTypeEntity_AUD ORDER BY REV ASC";
|
||||
Object[] results = (Object[]) entityManager.createNativeQuery( qry, "e1_e2" ).getSingleResult();
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
|
||||
Assert.assertNotNull( values );
|
||||
Assert.assertEquals( 1, values.size() );
|
||||
Object[] results = values.get( 0 );
|
||||
Assert.assertNotNull( results );
|
||||
Assert.assertEquals( 2, results.length );
|
||||
Assert.assertEquals( "X", results[0] );
|
||||
// Compare the Strings to account for, as an example, Oracle
|
||||
|
|
|
@ -40,4 +40,4 @@ logger.jdbc-extract.name=org.hibernate.orm.jdbc.extract
|
|||
logger.jdbc-extract.level=trace
|
||||
|
||||
logger.additional-jaxb-mapping-producer-impl.name=org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl
|
||||
logger.additional-jaxb-mapping-producer-impl.level=trace
|
||||
logger.additional-jaxb-mapping-producer-impl.level=trace
|
||||
|
|
|
@ -63,6 +63,7 @@ public class EntityOfBasics {
|
|||
private Date theTimestamp;
|
||||
private Instant theInstant;
|
||||
private Gender gender;
|
||||
private Gender singleCharGender;
|
||||
private Gender convertedGender;
|
||||
private Gender ordinalGender;
|
||||
private Duration theDuration;
|
||||
|
@ -148,6 +149,16 @@ public class EntityOfBasics {
|
|||
this.gender = gender;
|
||||
}
|
||||
|
||||
@Enumerated( EnumType.STRING )
|
||||
@Column( length = 1 )
|
||||
public Gender getSingleCharGender() {
|
||||
return singleCharGender;
|
||||
}
|
||||
|
||||
public void setSingleCharGender(Gender singleCharGender) {
|
||||
this.singleCharGender = singleCharGender;
|
||||
}
|
||||
|
||||
@Convert( converter = GenderConverter.class )
|
||||
@Column(name = "converted_gender", length = 1)
|
||||
@JdbcTypeCode( Types.CHAR )
|
||||
|
|
Loading…
Reference in New Issue