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