HHH-15276 - Introduce ConverterRegistration
This commit is contained in:
parent
d73a5cde38
commit
571d46bef8
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
/**
|
||||
* Registers an {@link jakarta.persistence.AttributeConverter}. The main
|
||||
* purpose is to be able to control {@link jakarta.persistence.Converter#autoApply()}
|
||||
* external to the actual converter class, which might be useful for third-parties
|
||||
* converters.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public @interface ConverterRegistration {
|
||||
/**
|
||||
* The converter class to register
|
||||
*/
|
||||
Class<? extends AttributeConverter<?,?>> converter();
|
||||
|
||||
/**
|
||||
* The domain type to which this converter should be applied. This allows
|
||||
* refining the domain type associated with the converter e.g. to apply to
|
||||
* a subtype.
|
||||
* <p/>
|
||||
* With {@link #autoApply()} set to true, this will effectively override converters
|
||||
* defined with {@link Converter#autoApply()} set to {@code false} and auto-apply them.
|
||||
* <p/>
|
||||
* With {@link #autoApply()} set to false, this will effectively override converters
|
||||
* defined with {@link Converter#autoApply()} set to {@code true} and disable auto-apply
|
||||
* for them.
|
||||
*/
|
||||
Class<?> domainType() default void.class;
|
||||
|
||||
/**
|
||||
* Should the registered converter be auto applied for
|
||||
* converting values of its reported domain type?
|
||||
* <p/>
|
||||
* Defaults to true as that is the more common use case for this annotation.
|
||||
*/
|
||||
boolean autoApply() default true;
|
||||
}
|
|
@ -473,7 +473,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
// attribute converters
|
||||
|
||||
@Override
|
||||
public void addAttributeConverter(Class<? extends AttributeConverter> converterClass) {
|
||||
public void addAttributeConverter(Class<? extends AttributeConverter<?,?>> converterClass) {
|
||||
attributeConverterManager.addConverter(
|
||||
new ClassBasedConverterDescriptor( converterClass, getBootstrapContext().getClassmateContext() )
|
||||
);
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
package org.hibernate.boot.model.convert.internal;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.model.convert.spi.AutoApplicableConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
|
@ -21,12 +18,16 @@ import org.hibernate.resource.beans.spi.ManagedBean;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
import static org.hibernate.boot.model.convert.internal.ConverterHelper.resolveConverterClassParamTypes;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractConverterDescriptor implements ConverterDescriptor {
|
||||
private final Class<? extends AttributeConverter> converterClass;
|
||||
private final Class<? extends AttributeConverter<?,?>> converterClass;
|
||||
|
||||
private final ResolvedType domainType;
|
||||
private final ResolvedType jdbcType;
|
||||
|
@ -34,25 +35,12 @@ public abstract class AbstractConverterDescriptor implements ConverterDescriptor
|
|||
private final AutoApplicableConverterDescriptor autoApplicableDescriptor;
|
||||
|
||||
public AbstractConverterDescriptor(
|
||||
Class<? extends AttributeConverter> converterClass,
|
||||
Class<? extends AttributeConverter<?,?>> converterClass,
|
||||
Boolean forceAutoApply,
|
||||
ClassmateContext classmateContext) {
|
||||
this.converterClass = converterClass;
|
||||
|
||||
final ResolvedType converterType = classmateContext.getTypeResolver().resolve( converterClass );
|
||||
final List<ResolvedType> converterParamTypes = converterType.typeParametersFor( AttributeConverter.class );
|
||||
if ( converterParamTypes == null ) {
|
||||
throw new AnnotationException(
|
||||
"Could not extract type parameter information from AttributeConverter implementation ["
|
||||
+ converterClass.getName() + "]"
|
||||
);
|
||||
}
|
||||
else if ( converterParamTypes.size() != 2 ) {
|
||||
throw new AnnotationException(
|
||||
"Unexpected type parameter information for AttributeConverter implementation [" +
|
||||
converterClass.getName() + "]; expected 2 parameter types, but found " + converterParamTypes.size()
|
||||
);
|
||||
}
|
||||
final List<ResolvedType> converterParamTypes = resolveConverterClassParamTypes( converterClass, classmateContext );
|
||||
|
||||
this.domainType = converterParamTypes.get( 0 );
|
||||
this.jdbcType = converterParamTypes.get( 1 );
|
||||
|
@ -81,7 +69,7 @@ public abstract class AbstractConverterDescriptor implements ConverterDescriptor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AttributeConverter> getAttributeConverterClass() {
|
||||
public Class<? extends AttributeConverter<?,?>> getAttributeConverterClass() {
|
||||
return converterClass;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,25 +15,58 @@ import java.util.Map;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.model.convert.spi.AutoApplicableConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterAutoApplyHandler;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.RegisteredConversion;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @implNote It is important that all {@link RegisteredConversion} be registered
|
||||
* prior to attempts to register any {@link ConverterDescriptor}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AttributeConverterManager implements ConverterAutoApplyHandler {
|
||||
private static final Logger log = Logger.getLogger( AttributeConverterManager.class );
|
||||
|
||||
private Map<Class, ConverterDescriptor> attributeConverterDescriptorsByClass;
|
||||
private Map<Class<?>, ConverterDescriptor> attributeConverterDescriptorsByClass;
|
||||
private Map<Class<?>, RegisteredConversion> registeredConversionsByDomainType;
|
||||
|
||||
public void addConverter(ConverterDescriptor descriptor) {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.tracef( "Starting AttributeConverterManager#addConverter : `%s`", descriptor.getAttributeConverterClass().getName() );
|
||||
}
|
||||
|
||||
if ( registeredConversionsByDomainType != null ) {
|
||||
final ResolvedType domainValueResolvedType = descriptor.getDomainValueResolvedType();
|
||||
final Class<?> domainType = domainValueResolvedType.getErasedType();
|
||||
final RegisteredConversion registeredConversion = registeredConversionsByDomainType.get( domainType );
|
||||
if ( registeredConversion != null ) {
|
||||
// we can skip the registering the converter...
|
||||
// the RegisteredConversion will always take precedence
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Skipping registration of discovered AttributeConverter `%s` for auto-apply; there was" +
|
||||
"already ",
|
||||
descriptor.getAttributeConverterClass().getName()
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( attributeConverterDescriptorsByClass == null ) {
|
||||
attributeConverterDescriptorsByClass = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
@ -54,6 +87,49 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void addRegistration(RegisteredConversion conversion, BootstrapContext context) {
|
||||
if ( registeredConversionsByDomainType == null ) {
|
||||
registeredConversionsByDomainType = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
final Class<?> domainType;
|
||||
if ( conversion.getExplicitDomainType().equals( void.class ) ) {
|
||||
// the registration did not define an explicit domain-type, so inspect the converter
|
||||
final ClassmateContext classmateContext = context.getClassmateContext();
|
||||
final ResolvedType converterType = classmateContext.getTypeResolver().resolve( conversion.getConverterType() );
|
||||
final List<ResolvedType> converterParamTypes = converterType.typeParametersFor( AttributeConverter.class );
|
||||
if ( converterParamTypes == null ) {
|
||||
throw new AnnotationException(
|
||||
"Could not extract type parameter information from AttributeConverter implementation ["
|
||||
+ conversion.getConverterType().getName() + "]"
|
||||
);
|
||||
}
|
||||
else if ( converterParamTypes.size() != 2 ) {
|
||||
throw new AnnotationException(
|
||||
"Unexpected type parameter information for AttributeConverter implementation [" +
|
||||
conversion.getConverterType().getName() + "]; expected 2 parameter types, but found " + converterParamTypes.size()
|
||||
);
|
||||
}
|
||||
|
||||
domainType = converterParamTypes.get( 0 ).getErasedType();
|
||||
}
|
||||
else {
|
||||
domainType = conversion.getExplicitDomainType();
|
||||
}
|
||||
|
||||
// see if we have a matching entry in `attributeConverterDescriptorsByClass`.
|
||||
// if so, remove it. The conversion being registered will always take precedence
|
||||
final ConverterDescriptor removed = attributeConverterDescriptorsByClass.remove( conversion.getConverterType() );
|
||||
if ( removed != null && log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Removed potentially auto-applicable converter `%s` due to @ConverterRegistration",
|
||||
removed.getAttributeConverterClass().getName()
|
||||
);
|
||||
}
|
||||
|
||||
registeredConversionsByDomainType.put( domainType, conversion );
|
||||
}
|
||||
|
||||
private Collection<ConverterDescriptor> converterDescriptors() {
|
||||
if ( attributeConverterDescriptorsByClass == null ) {
|
||||
return Collections.emptyList();
|
||||
|
@ -83,17 +159,33 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
|
|||
return locateMatchingConverter(
|
||||
property,
|
||||
ConversionSite.ATTRIBUTE,
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForAttribute( property, context )
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForAttribute( property, context ),
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
private static StringHelper.Renderer<ConverterDescriptor> RENDERER = value -> value.getAttributeConverterClass().getName();
|
||||
private static final StringHelper.Renderer<ConverterDescriptor> RENDERER = value -> value.getAttributeConverterClass().getName();
|
||||
|
||||
private ConverterDescriptor locateMatchingConverter(
|
||||
XProperty xProperty,
|
||||
ConversionSite conversionSite,
|
||||
Function<AutoApplicableConverterDescriptor, ConverterDescriptor> matcher) {
|
||||
List<ConverterDescriptor> matches = new ArrayList<>();
|
||||
Function<AutoApplicableConverterDescriptor, ConverterDescriptor> matcher,
|
||||
MetadataBuildingContext context) {
|
||||
if ( registeredConversionsByDomainType != null ) {
|
||||
// we had registered conversions - see if any of them match and, if so, use that conversion
|
||||
final ResolvedType resolveAttributeType = ConverterHelper.resolveAttributeType( xProperty, context );
|
||||
final RegisteredConversion registrationForDomainType = registeredConversionsByDomainType.get( resolveAttributeType.getErasedType() );
|
||||
if ( registrationForDomainType != null ) {
|
||||
if ( registrationForDomainType.isAutoApply() ) {
|
||||
return registrationForDomainType.getConverterDescriptor();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<ConverterDescriptor> matches = new ArrayList<>();
|
||||
|
||||
for ( ConverterDescriptor descriptor : converterDescriptors() ) {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
|
@ -143,7 +235,8 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
|
|||
return locateMatchingConverter(
|
||||
property,
|
||||
ConversionSite.COLLECTION_ELEMENT,
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForCollectionElement( property, context )
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForCollectionElement( property, context ),
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -154,7 +247,8 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
|
|||
return locateMatchingConverter(
|
||||
property,
|
||||
ConversionSite.MAP_KEY,
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForMapKey( property, context )
|
||||
(autoApplyDescriptor) -> autoApplyDescriptor.getAutoAppliedConverterDescriptorForMapKey( property, context ),
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,27 +6,17 @@
|
|||
*/
|
||||
package org.hibernate.boot.model.convert.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.model.convert.spi.AutoApplicableConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.annotations.HCANNHelper;
|
||||
import org.hibernate.internal.util.type.PrimitiveWrapperHelper;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
|
||||
/**
|
||||
* Standard implementation of AutoApplicableConverterDescriptor
|
||||
|
@ -44,9 +34,9 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
|
|||
public ConverterDescriptor getAutoAppliedConverterDescriptorForAttribute(
|
||||
XProperty xProperty,
|
||||
MetadataBuildingContext context) {
|
||||
final ResolvedType attributeType = resolveAttributeType( xProperty, context );
|
||||
final ResolvedType attributeType = ConverterHelper.resolveAttributeType( xProperty, context );
|
||||
|
||||
return typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), attributeType )
|
||||
return ConverterHelper.typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), attributeType )
|
||||
? linkedConverterDescriptor
|
||||
: null;
|
||||
}
|
||||
|
@ -55,7 +45,7 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
|
|||
public ConverterDescriptor getAutoAppliedConverterDescriptorForCollectionElement(
|
||||
XProperty xProperty,
|
||||
MetadataBuildingContext context) {
|
||||
final ResolvedMember collectionMember = resolveMember( xProperty, context );
|
||||
final ResolvedMember<?> collectionMember = ConverterHelper.resolveMember( xProperty, context );
|
||||
|
||||
final ResolvedType elementType;
|
||||
if ( Map.class.isAssignableFrom( collectionMember.getType().getErasedType() ) ) {
|
||||
|
@ -68,7 +58,7 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
|
|||
throw new HibernateException( "Attribute was neither a Collection nor a Map : " + collectionMember.getType().getErasedType() );
|
||||
}
|
||||
|
||||
return typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), elementType )
|
||||
return ConverterHelper.typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), elementType )
|
||||
? linkedConverterDescriptor
|
||||
: null;
|
||||
}
|
||||
|
@ -78,7 +68,7 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
|
|||
XProperty xProperty,
|
||||
MetadataBuildingContext context) {
|
||||
|
||||
final ResolvedMember collectionMember = resolveMember( xProperty, context );
|
||||
final ResolvedMember<?> collectionMember = ConverterHelper.resolveMember( xProperty, context );
|
||||
final ResolvedType keyType;
|
||||
|
||||
if ( Map.class.isAssignableFrom( collectionMember.getType().getErasedType() ) ) {
|
||||
|
@ -88,102 +78,10 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
|
|||
throw new HibernateException( "Attribute was not a Map : " + collectionMember.getType().getErasedType() );
|
||||
}
|
||||
|
||||
return typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), keyType )
|
||||
return ConverterHelper.typesMatch( linkedConverterDescriptor.getDomainValueResolvedType(), keyType )
|
||||
? linkedConverterDescriptor
|
||||
: null;
|
||||
}
|
||||
|
||||
private ResolvedType resolveAttributeType(XProperty xProperty, MetadataBuildingContext context) {
|
||||
return resolveMember( xProperty, context ).getType();
|
||||
}
|
||||
|
||||
private ResolvedMember resolveMember(XProperty xProperty, MetadataBuildingContext buildingContext) {
|
||||
final ClassmateContext classmateContext = buildingContext.getBootstrapContext().getClassmateContext();
|
||||
final ReflectionManager reflectionManager = buildingContext.getBootstrapContext().getReflectionManager();
|
||||
|
||||
final ResolvedType declaringClassType = classmateContext.getTypeResolver().resolve(
|
||||
reflectionManager.toClass( xProperty.getDeclaringClass() )
|
||||
);
|
||||
final ResolvedTypeWithMembers declaringClassWithMembers = classmateContext.getMemberResolver().resolve(
|
||||
declaringClassType,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
final Member member = toMember( xProperty );
|
||||
if ( member instanceof Method ) {
|
||||
for ( ResolvedMethod resolvedMember : declaringClassWithMembers.getMemberMethods() ) {
|
||||
if ( resolvedMember.getName().equals( member.getName() ) ) {
|
||||
return resolvedMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( member instanceof Field ) {
|
||||
for ( ResolvedField resolvedMember : declaringClassWithMembers.getMemberFields() ) {
|
||||
if ( resolvedMember.getName().equals( member.getName() ) ) {
|
||||
return resolvedMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Unexpected java.lang.reflect.Member type from org.hibernate.annotations.common.reflection.java.JavaXMember : " + member );
|
||||
}
|
||||
|
||||
throw new HibernateException(
|
||||
"Could not locate resolved type information for attribute [" + member.getName() + "] from Classmate"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static Member toMember(XProperty xProperty) {
|
||||
try {
|
||||
return HCANNHelper.getUnderlyingMember( xProperty );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(
|
||||
"Could not resolve member signature from XProperty reference",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean typesMatch(ResolvedType converterDefinedType, ResolvedType checkType) {
|
||||
Class<?> erasedCheckType = checkType.getErasedType();
|
||||
if ( erasedCheckType.isPrimitive() ) {
|
||||
erasedCheckType = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( erasedCheckType ).getWrapperClass();
|
||||
}
|
||||
if ( !converterDefinedType.getErasedType().isAssignableFrom( erasedCheckType ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the converter did not define any nested type parameters, then the check above is
|
||||
// enough for a match
|
||||
if ( converterDefinedType.getTypeParameters().isEmpty() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// however, here the converter *did* define nested type parameters, so we'd have a converter defined using something like, e.g., List<String> for its
|
||||
// domain type.
|
||||
//
|
||||
// we need to check those nested types as well
|
||||
|
||||
if ( checkType.getTypeParameters().isEmpty() ) {
|
||||
// the domain type did not define nested type params. a List<String> would not auto-match a List(<Object>)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( converterDefinedType.getTypeParameters().size() != checkType.getTypeParameters().size() ) {
|
||||
// they had different number of type params somehow.
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < converterDefinedType.getTypeParameters().size(); i++ ) {
|
||||
if ( !typesMatch( converterDefinedType.getTypeParameters().get( i ), checkType.getTypeParameters().get( i ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.boot.model.convert.internal;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* ConverterDescriptor implementation for cases where we know the
|
||||
* AttributeConverter Class. This is the normal case.
|
||||
|
@ -20,13 +20,13 @@ import org.hibernate.resource.beans.spi.ManagedBean;
|
|||
*/
|
||||
public class ClassBasedConverterDescriptor extends AbstractConverterDescriptor {
|
||||
public ClassBasedConverterDescriptor(
|
||||
Class<? extends AttributeConverter> converterClass,
|
||||
Class<? extends AttributeConverter<?,?>> converterClass,
|
||||
ClassmateContext classmateContext) {
|
||||
super( converterClass, null, classmateContext );
|
||||
}
|
||||
|
||||
public ClassBasedConverterDescriptor(
|
||||
Class<? extends AttributeConverter> converterClass,
|
||||
Class<? extends AttributeConverter<?,?>> converterClass,
|
||||
Boolean forceAutoApply,
|
||||
ClassmateContext classmateContext) {
|
||||
super( converterClass, forceAutoApply, classmateContext );
|
||||
|
|
|
@ -6,10 +6,27 @@
|
|||
*/
|
||||
package org.hibernate.boot.model.convert.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.annotations.HCANNHelper;
|
||||
import org.hibernate.internal.util.GenericsHelper;
|
||||
import org.hibernate.internal.util.type.PrimitiveWrapperHelper;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import com.fasterxml.classmate.members.ResolvedField;
|
||||
import com.fasterxml.classmate.members.ResolvedMember;
|
||||
import com.fasterxml.classmate.members.ResolvedMethod;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
|
@ -19,4 +36,125 @@ public class ConverterHelper {
|
|||
public static ParameterizedType extractAttributeConverterParameterizedType(Class<? extends AttributeConverter<?,?>> base) {
|
||||
return GenericsHelper.extractParameterizedType( base );
|
||||
}
|
||||
|
||||
public static ResolvedType resolveAttributeType(XProperty xProperty, MetadataBuildingContext context) {
|
||||
return resolveMember( xProperty, context ).getType();
|
||||
}
|
||||
|
||||
public static ResolvedMember<? extends Member> resolveMember(XProperty xProperty, MetadataBuildingContext buildingContext) {
|
||||
final ClassmateContext classmateContext = buildingContext.getBootstrapContext().getClassmateContext();
|
||||
final ReflectionManager reflectionManager = buildingContext.getBootstrapContext().getReflectionManager();
|
||||
|
||||
final ResolvedType declaringClassType = classmateContext.getTypeResolver().resolve(
|
||||
reflectionManager.toClass( xProperty.getDeclaringClass() )
|
||||
);
|
||||
final ResolvedTypeWithMembers declaringClassWithMembers = classmateContext.getMemberResolver().resolve(
|
||||
declaringClassType,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
final Member member = toMember( xProperty );
|
||||
if ( member instanceof Method ) {
|
||||
for ( ResolvedMethod resolvedMember : declaringClassWithMembers.getMemberMethods() ) {
|
||||
if ( resolvedMember.getName().equals( member.getName() ) ) {
|
||||
return resolvedMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( member instanceof Field ) {
|
||||
for ( ResolvedField resolvedMember : declaringClassWithMembers.getMemberFields() ) {
|
||||
if ( resolvedMember.getName().equals( member.getName() ) ) {
|
||||
return resolvedMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Unexpected java.lang.reflect.Member type from org.hibernate.annotations.common.reflection.java.JavaXMember : " + member );
|
||||
}
|
||||
|
||||
throw new HibernateException(
|
||||
"Could not locate resolved type information for attribute [" + member.getName() + "] from Classmate"
|
||||
);
|
||||
}
|
||||
|
||||
public static Member toMember(XProperty xProperty) {
|
||||
try {
|
||||
return HCANNHelper.getUnderlyingMember( xProperty );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(
|
||||
"Could not resolve member signature from XProperty reference",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ResolvedType> resolveConverterClassParamTypes(
|
||||
Class<? extends AttributeConverter<?, ?>> converterClass,
|
||||
ClassmateContext context) {
|
||||
final ResolvedType converterType = context.getTypeResolver().resolve( converterClass );
|
||||
final List<ResolvedType> converterParamTypes = converterType.typeParametersFor( AttributeConverter.class );
|
||||
if ( converterParamTypes == null ) {
|
||||
throw new AnnotationException(
|
||||
"Could not extract type parameter information from AttributeConverter implementation ["
|
||||
+ converterClass.getName() + "]"
|
||||
);
|
||||
}
|
||||
else if ( converterParamTypes.size() != 2 ) {
|
||||
throw new AnnotationException(
|
||||
"Unexpected type parameter information for AttributeConverter implementation [" +
|
||||
converterClass.getName() + "]; expected 2 parameter types, but found " + converterParamTypes.size()
|
||||
);
|
||||
}
|
||||
return converterParamTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether 2 types match. Intended for determining whether to auto applying a converter
|
||||
*
|
||||
* @param converterDefinedType The type defined via the converter's parameterized type signature.
|
||||
* E.g. {@code O} in {@code implements AttributeConverter<O,R>}
|
||||
* @param checkType The type from the domain model (basic attribute type, Map key type, Collection element type)
|
||||
*
|
||||
* @return {@code true} if they match, otherwise {@code false}.
|
||||
*/
|
||||
public static boolean typesMatch(ResolvedType converterDefinedType, ResolvedType checkType) {
|
||||
Class<?> erasedCheckType = checkType.getErasedType();
|
||||
if ( erasedCheckType.isPrimitive() ) {
|
||||
erasedCheckType = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( erasedCheckType ).getWrapperClass();
|
||||
}
|
||||
if ( !converterDefinedType.getErasedType().isAssignableFrom( erasedCheckType ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the converter did not define any nested type parameters, then the check above is
|
||||
// enough for a match
|
||||
if ( converterDefinedType.getTypeParameters().isEmpty() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// however, here the converter *did* define nested type parameters, so we'd have a converter defined using something like, e.g., List<String> for its
|
||||
// domain type.
|
||||
//
|
||||
// we need to check those nested types as well
|
||||
|
||||
if ( checkType.getTypeParameters().isEmpty() ) {
|
||||
// the domain type did not define nested type params. a List<String> would not auto-match a List(<Object>)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( converterDefinedType.getTypeParameters().size() != checkType.getTypeParameters().size() ) {
|
||||
// they had different number of type params somehow.
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < converterDefinedType.getTypeParameters().size(); i++ ) {
|
||||
if ( !typesMatch( converterDefinedType.getTypeParameters().get( i ), checkType.getTypeParameters().get( i ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
*/
|
||||
package org.hibernate.boot.model.convert.internal;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* ConverterDescriptor implementation for cases where we are handed
|
||||
* the AttributeConverter instance to use.
|
||||
|
@ -28,11 +28,12 @@ public class InstanceBasedConverterDescriptor extends AbstractConverterDescripto
|
|||
this( converterInstance, null, classmateContext );
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public InstanceBasedConverterDescriptor(
|
||||
AttributeConverter<?,?> converterInstance,
|
||||
Boolean forceAutoApply,
|
||||
ClassmateContext classmateContext) {
|
||||
super( converterInstance.getClass(), forceAutoApply, classmateContext );
|
||||
super( (Class) converterInstance.getClass(), forceAutoApply, classmateContext );
|
||||
this.converterInstance = converterInstance;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.boot.model.convert.spi;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* Boot-time descriptor of a JPA AttributeConverter
|
||||
|
@ -23,7 +22,7 @@ public interface ConverterDescriptor {
|
|||
/**
|
||||
* The AttributeConverter class
|
||||
*/
|
||||
Class<? extends AttributeConverter> getAttributeConverterClass();
|
||||
Class<? extends AttributeConverter<?,?>> getAttributeConverterClass();
|
||||
|
||||
/**
|
||||
* The resolved Classmate type descriptor for the conversion's domain type
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.boot.model.convert.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.model.convert.internal.AutoApplicableConverterDescriptorBypassedImpl;
|
||||
import org.hibernate.boot.model.convert.internal.AutoApplicableConverterDescriptorStandardImpl;
|
||||
import org.hibernate.boot.model.convert.internal.ConverterHelper;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedType;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* A registered conversion.
|
||||
*
|
||||
* @see org.hibernate.annotations.ConverterRegistration
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class RegisteredConversion {
|
||||
private final Class<?> explicitDomainType;
|
||||
private final Class<? extends AttributeConverter<?,?>> converterType;
|
||||
private final boolean autoApply;
|
||||
|
||||
private final ConverterDescriptor converterDescriptor;
|
||||
|
||||
public RegisteredConversion(
|
||||
Class<?> explicitDomainType,
|
||||
Class<? extends AttributeConverter<?,?>> converterType,
|
||||
boolean autoApply,
|
||||
MetadataBuildingContext context) {
|
||||
this.explicitDomainType = explicitDomainType;
|
||||
this.converterType = converterType;
|
||||
this.autoApply = autoApply;
|
||||
|
||||
this.converterDescriptor = determineConverterDescriptor( explicitDomainType, converterType, autoApply, context );
|
||||
}
|
||||
|
||||
private static ConverterDescriptor determineConverterDescriptor(
|
||||
Class<?> explicitDomainType,
|
||||
Class<? extends AttributeConverter<?, ?>> converterType,
|
||||
boolean autoApply,
|
||||
MetadataBuildingContext context) {
|
||||
final List<ResolvedType> resolvedParamTypes = ConverterHelper.resolveConverterClassParamTypes(
|
||||
converterType,
|
||||
context.getBootstrapContext().getClassmateContext()
|
||||
);
|
||||
final ResolvedType relationalType = resolvedParamTypes.get( 1 );
|
||||
final ResolvedType domainTypeToMatch;
|
||||
if ( explicitDomainType != null ) {
|
||||
domainTypeToMatch = context.getBootstrapContext().getClassmateContext().getTypeResolver().resolve( explicitDomainType );
|
||||
}
|
||||
else {
|
||||
domainTypeToMatch = resolvedParamTypes.get( 0 );
|
||||
}
|
||||
|
||||
return new ConverterDescriptorImpl( converterType, domainTypeToMatch, relationalType, autoApply );
|
||||
}
|
||||
|
||||
public Class<?> getExplicitDomainType() {
|
||||
return explicitDomainType;
|
||||
}
|
||||
|
||||
public Class<?> getConverterType() {
|
||||
return converterType;
|
||||
}
|
||||
|
||||
public boolean isAutoApply() {
|
||||
return autoApply;
|
||||
}
|
||||
|
||||
public ConverterDescriptor getConverterDescriptor() {
|
||||
return converterDescriptor;
|
||||
}
|
||||
|
||||
private static class ConverterDescriptorImpl implements ConverterDescriptor {
|
||||
private final Class<? extends AttributeConverter<?, ?>> converterType;
|
||||
private final ResolvedType domainTypeToMatch;
|
||||
private final ResolvedType relationalType;
|
||||
private final boolean autoApply;
|
||||
|
||||
private final AutoApplicableConverterDescriptor autoApplyDescriptor;
|
||||
|
||||
public ConverterDescriptorImpl(
|
||||
Class<? extends AttributeConverter<?, ?>> converterType,
|
||||
ResolvedType domainTypeToMatch,
|
||||
ResolvedType relationalType,
|
||||
boolean autoApply) {
|
||||
this.converterType = converterType;
|
||||
this.domainTypeToMatch = domainTypeToMatch;
|
||||
this.relationalType = relationalType;
|
||||
this.autoApply = autoApply;
|
||||
|
||||
this.autoApplyDescriptor = autoApply
|
||||
? new AutoApplicableConverterDescriptorStandardImpl( this )
|
||||
: AutoApplicableConverterDescriptorBypassedImpl.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AttributeConverter<?, ?>> getAttributeConverterClass() {
|
||||
return converterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedType getDomainValueResolvedType() {
|
||||
return domainTypeToMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedType getRelationalValueResolvedType() {
|
||||
return relationalType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoApplicableConverterDescriptor getAutoApplyDescriptor() {
|
||||
return autoApplyDescriptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JpaAttributeConverter<?, ?> createJpaAttributeConverter(JpaAttributeConverterCreationContext context) {
|
||||
final ManagedBean<? extends AttributeConverter<?, ?>> converterBean = context
|
||||
.getManagedBeanRegistry()
|
||||
.getBean( converterType );
|
||||
|
||||
final TypeConfiguration typeConfiguration = context.getTypeConfiguration();
|
||||
final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry();
|
||||
javaTypeRegistry.resolveDescriptor( domainTypeToMatch.getErasedType() );
|
||||
|
||||
//noinspection rawtypes
|
||||
return new JpaAttributeConverterImpl(
|
||||
converterBean,
|
||||
javaTypeRegistry.getDescriptor( converterBean.getBeanClass() ),
|
||||
javaTypeRegistry.resolveDescriptor( domainTypeToMatch.getErasedType() ),
|
||||
javaTypeRegistry.resolveDescriptor( relationalType.getErasedType() )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -50,7 +50,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
|
||||
private final MetadataBuildingContextRootImpl rootMetadataBuildingContext;
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
@SuppressWarnings({ "FieldCanBeLocal", "unused" })
|
||||
private final IndexView jandexView;
|
||||
|
||||
private final ReflectionManager reflectionManager;
|
||||
|
@ -112,8 +112,8 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
final XClass xClass = reflectionManager.toXClass( annotatedClass );
|
||||
// categorize it, based on assumption it does not fall into multiple categories
|
||||
if ( xClass.isAnnotationPresent( Converter.class ) ) {
|
||||
//noinspection unchecked, rawtypes
|
||||
attributeConverterManager.addAttributeConverter( (Class<? extends AttributeConverter>) annotatedClass );
|
||||
//noinspection unchecked
|
||||
attributeConverterManager.addAttributeConverter( (Class<? extends AttributeConverter<?,?>>) annotatedClass );
|
||||
}
|
||||
else if ( xClass.isAnnotationPresent( Entity.class )
|
||||
|| xClass.isAnnotationPresent( MappedSuperclass.class ) ) {
|
||||
|
@ -319,8 +319,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
rootMetadataBuildingContext.getMetadataCollector().addAttributeConverter( descriptor );
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void addAttributeConverter(Class<? extends AttributeConverter> converterClass) {
|
||||
public void addAttributeConverter(Class<? extends AttributeConverter<?,?>> converterClass) {
|
||||
rootMetadataBuildingContext.getMetadataCollector().addAttributeConverter( converterClass );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -19,7 +18,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.CollectionTypeRegistration;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.boot.internal.ClassmateContext;
|
||||
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
|
||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||
import org.hibernate.boot.model.TypeDefinition;
|
||||
|
@ -232,8 +230,7 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
|
|||
/**
|
||||
* Apply an {@link AttributeConverter}
|
||||
*/
|
||||
void addAttributeConverter(Class<? extends AttributeConverter> converterClass);
|
||||
|
||||
void addAttributeConverter(Class<? extends AttributeConverter<?,?>> converterClass);
|
||||
|
||||
ConverterAutoApplyHandler getAttributeConverterAutoApplyHandler();
|
||||
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Convert;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||
|
||||
/**
|
||||
* Describes a {@link jakarta.persistence.Convert} conversion
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AttributeConversionInfo {
|
||||
private final Class<? extends AttributeConverter> converterClass;
|
||||
private final Class<? extends AttributeConverter<?,?>> converterClass;
|
||||
private final boolean conversionDisabled;
|
||||
|
||||
private final String attributeName;
|
||||
|
@ -25,7 +25,7 @@ public class AttributeConversionInfo {
|
|||
private final XAnnotatedElement source;
|
||||
|
||||
public AttributeConversionInfo(
|
||||
Class<? extends AttributeConverter> converterClass,
|
||||
Class<? extends AttributeConverter<?,?>> converterClass,
|
||||
boolean conversionDisabled,
|
||||
String attributeName,
|
||||
XAnnotatedElement source) {
|
||||
|
@ -45,7 +45,7 @@ public class AttributeConversionInfo {
|
|||
);
|
||||
}
|
||||
|
||||
public Class<? extends AttributeConverter> getConverterClass() {
|
||||
public Class<? extends AttributeConverter<?,?>> getConverterClass() {
|
||||
return converterClass;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ public class XMLContext implements Serializable {
|
|||
* @param entityMappings The xml document to add
|
||||
* @return Add an xml document to this context and return the list of added class names.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> addDocument(JaxbEntityMappings entityMappings) {
|
||||
hasContext = true;
|
||||
|
||||
|
@ -172,7 +171,7 @@ public class XMLContext implements Serializable {
|
|||
final boolean autoApply = Boolean.TRUE.equals( converterElement.isAutoApply() );
|
||||
|
||||
try {
|
||||
final Class<? extends AttributeConverter> attributeConverterClass = classLoaderAccess.classForName(
|
||||
final Class<? extends AttributeConverter<?,?>> attributeConverterClass = classLoaderAccess.classForName(
|
||||
buildSafeClassName( className, packageName )
|
||||
);
|
||||
converterDescriptors.add(
|
||||
|
@ -231,7 +230,7 @@ public class XMLContext implements Serializable {
|
|||
return hasContext;
|
||||
}
|
||||
|
||||
private List<ConverterDescriptor> converterDescriptors = new ArrayList<>();
|
||||
private final List<ConverterDescriptor> converterDescriptors = new ArrayList<>();
|
||||
|
||||
public void applyDiscoveredAttributeConverters(AttributeConverterDefinitionCollector collector) {
|
||||
for ( ConverterDescriptor descriptor : converterDescriptors ) {
|
||||
|
|
|
@ -1254,10 +1254,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
List<ConverterDescriptor> converterDescriptors = null;
|
||||
|
||||
// add any explicit Class references passed in
|
||||
final List<Class<? extends AttributeConverter>> loadedAnnotatedClasses = (List<Class<? extends AttributeConverter>>)
|
||||
final List<Class<? extends AttributeConverter<?,?>>> loadedAnnotatedClasses = (List<Class<? extends AttributeConverter<?,?>>>)
|
||||
configurationValues.remove( AvailableSettings.LOADED_CLASSES );
|
||||
if ( loadedAnnotatedClasses != null ) {
|
||||
for ( Class<? extends AttributeConverter> cls : loadedAnnotatedClasses ) {
|
||||
for ( Class<? extends AttributeConverter<?,?>> cls : loadedAnnotatedClasses ) {
|
||||
if ( AttributeConverter.class.isAssignableFrom( cls ) ) {
|
||||
if ( converterDescriptors == null ) {
|
||||
converterDescriptors = new ArrayList<>();
|
||||
|
|
|
@ -735,7 +735,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
.getService( ClassLoaderService.class );
|
||||
try {
|
||||
//noinspection rawtypes
|
||||
final Class<AttributeConverter> converterClass = cls.classForName( converterClassName );
|
||||
final Class<AttributeConverter<?,?>> converterClass = cls.classForName( converterClassName );
|
||||
setAttributeConverterDescriptor( new ClassBasedConverterDescriptor(
|
||||
converterClass,
|
||||
false,
|
||||
|
|
Loading…
Reference in New Issue