HHH-17835 Custom ConvertedPrimitiveBasicTypeImpl type resolution

This commit is contained in:
Marco Belladelli 2024-03-11 22:53:41 +01:00
parent 50acce43c3
commit 37714a6b1a
4 changed files with 91 additions and 8 deletions

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.boot.model.process.internal; package org.hibernate.boot.model.process.internal;
import java.lang.reflect.Type;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -20,6 +21,7 @@ import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.converter.internal.AttributeConverterMutabilityPlanImpl; import org.hibernate.type.descriptor.converter.internal.AttributeConverterMutabilityPlanImpl;
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.descriptor.java.BasicJavaType; import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
@ -28,6 +30,7 @@ import org.hibernate.type.descriptor.java.MutabilityPlan;
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.JdbcTypeIndicators;
import org.hibernate.type.internal.CustomMutabilityConvertedBasicTypeImpl; import org.hibernate.type.internal.CustomMutabilityConvertedBasicTypeImpl;
import org.hibernate.type.internal.CustomMutabilityConvertedPrimitiveBasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
@ -40,6 +43,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
Function<TypeConfiguration, BasicJavaType> explicitJtdAccess, Function<TypeConfiguration, BasicJavaType> explicitJtdAccess,
Function<TypeConfiguration, JdbcType> explicitStdAccess, Function<TypeConfiguration, JdbcType> explicitStdAccess,
Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess, Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess,
Type resolvedJavaType,
JdbcTypeIndicators sqlTypeIndicators, JdbcTypeIndicators sqlTypeIndicators,
JpaAttributeConverterCreationContext converterCreationContext, JpaAttributeConverterCreationContext converterCreationContext,
MetadataBuildingContext context) { MetadataBuildingContext context) {
@ -48,6 +52,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
explicitStdAccess, explicitStdAccess,
explicitMutabilityPlanAccess, explicitMutabilityPlanAccess,
converter( converterCreationContext, converterDescriptor ), converter( converterCreationContext, converterDescriptor ),
resolvedJavaType,
sqlTypeIndicators, sqlTypeIndicators,
context context
); );
@ -76,6 +81,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
explicitStdAccess, explicitStdAccess,
explicitMutabilityPlanAccess, explicitMutabilityPlanAccess,
converter( converterCreationContext, converterDescriptor ), converter( converterCreationContext, converterDescriptor ),
null,
sqlTypeIndicators, sqlTypeIndicators,
context context
); );
@ -93,6 +99,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
Function<TypeConfiguration, JdbcType> explicitStdAccess, Function<TypeConfiguration, JdbcType> explicitStdAccess,
Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess, Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess,
JpaAttributeConverter<T,?> converter, JpaAttributeConverter<T,?> converter,
Type resolvedJavaType,
JdbcTypeIndicators sqlTypeIndicators, JdbcTypeIndicators sqlTypeIndicators,
MetadataBuildingContext context) { MetadataBuildingContext context) {
final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration(); final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration();
@ -122,12 +129,18 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
domainJtd domainJtd
); );
//noinspection unchecked
final Class<T> primitiveClass = resolvedJavaType instanceof Class<?> && ( (Class<?>) resolvedJavaType ).isPrimitive()
? (Class<T>) resolvedJavaType
: null;
return new NamedConverterResolution<>( return new NamedConverterResolution<>(
domainJtd, domainJtd,
relationalJtd, relationalJtd,
jdbcType, jdbcType,
converter, converter,
mutabilityPlan, mutabilityPlan,
primitiveClass,
context.getBootstrapContext().getTypeConfiguration() context.getBootstrapContext().getTypeConfiguration()
); );
} }
@ -182,6 +195,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
JdbcType jdbcType, JdbcType jdbcType,
JpaAttributeConverter<J,?> valueConverter, JpaAttributeConverter<J,?> valueConverter,
MutabilityPlan<J> mutabilityPlan, MutabilityPlan<J> mutabilityPlan,
Class<J> primitiveClass,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
assert domainJtd != null; assert domainJtd != null;
this.domainJtd = domainJtd; this.domainJtd = domainJtd;
@ -198,7 +212,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
assert mutabilityPlan != null; assert mutabilityPlan != null;
this.mutabilityPlan = mutabilityPlan; this.mutabilityPlan = mutabilityPlan;
this.legacyResolvedType = new CustomMutabilityConvertedBasicTypeImpl<>( this.legacyResolvedType = legacyResolvedType(
ConverterDescriptor.TYPE_NAME_PREFIX ConverterDescriptor.TYPE_NAME_PREFIX
+ valueConverter.getConverterJavaType().getTypeName(), + valueConverter.getConverterJavaType().getTypeName(),
String.format( String.format(
@ -208,11 +222,41 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
), ),
jdbcType, jdbcType,
valueConverter, valueConverter,
primitiveClass,
mutabilityPlan mutabilityPlan
); );
this.jdbcMapping = legacyResolvedType; this.jdbcMapping = legacyResolvedType;
} }
private static <J> BasicType<J> legacyResolvedType(
String name,
String description,
JdbcType jdbcType,
BasicValueConverter<J, ?> converter,
Class<J> primitiveClass,
MutabilityPlan<J> mutabilityPlan) {
if ( primitiveClass != null ) {
assert primitiveClass.isPrimitive();
return new CustomMutabilityConvertedPrimitiveBasicTypeImpl<>(
name,
description,
jdbcType,
converter,
primitiveClass,
mutabilityPlan
);
}
else {
return new CustomMutabilityConvertedBasicTypeImpl<>(
name,
description,
jdbcType,
converter,
mutabilityPlan
);
}
}
@Override @Override
public BasicType<J> getLegacyResolvedBasicType() { public BasicType<J> getLegacyResolvedBasicType() {
return legacyResolvedType; return legacyResolvedType;

View File

@ -670,6 +670,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
explicitJavaTypeAccess, explicitJavaTypeAccess,
explicitJdbcTypeAccess, explicitJdbcTypeAccess,
explicitMutabilityPlanAccess, explicitMutabilityPlanAccess,
resolvedJavaType,
this, this,
this, this,
getBuildingContext() getBuildingContext()

View File

@ -319,17 +319,18 @@ public class AttributeFactory {
); );
} }
@SuppressWarnings( "unchecked" )
private static <Y> DomainType<Y> basicDomainType(ValueContext typeContext, MetadataContext context) { private static <Y> DomainType<Y> basicDomainType(ValueContext typeContext, MetadataContext context) {
if ( typeContext.getJpaBindableType().isPrimitive() ) { final Value hibernateValue = typeContext.getHibernateValue();
// Special BasicDomainType necessary for primitive types in the JPA metamodel if ( typeContext.getJpaBindableType().isPrimitive()
@SuppressWarnings("unchecked") && ( (SimpleValue) hibernateValue ).getJpaAttributeConverterDescriptor() == null ) {
// Special BasicDomainType necessary for primitive types in the JPA metamodel.
// When a converted is applied to the attribute we already resolve to the correct type
final Class<Y> type = (Class<Y>) typeContext.getJpaBindableType(); final Class<Y> type = (Class<Y>) typeContext.getJpaBindableType();
return context.resolveBasicType(type); return context.resolveBasicType( type );
} }
else { else {
@SuppressWarnings("unchecked") return (DomainType<Y>) hibernateValue.getType();
final DomainType<Y> type = (DomainType<Y>) typeContext.getHibernateValue().getType();
return type;
} }
} }

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.type.internal;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.JdbcType;
/**
* Wrapper of {@link CustomMutabilityConvertedBasicTypeImpl} for primitive type.
*
* @author Marco Belladelli
*/
public class CustomMutabilityConvertedPrimitiveBasicTypeImpl<J> extends CustomMutabilityConvertedBasicTypeImpl<J> {
private final Class<J> primitiveClass;
public CustomMutabilityConvertedPrimitiveBasicTypeImpl(
String name,
String description,
JdbcType jdbcType,
BasicValueConverter<J, ?> converter,
Class<J> primitiveClass,
MutabilityPlan<J> mutabilityPlan) {
super( name, description, jdbcType, converter, mutabilityPlan );
assert primitiveClass.isPrimitive();
this.primitiveClass = primitiveClass;
}
@Override
public Class<J> getJavaType() {
return primitiveClass;
}
}