improve the error message and add comments

This commit is contained in:
Gavin King 2024-12-31 12:50:59 +01:00
parent 9ff21ad449
commit abf55433a2
5 changed files with 44 additions and 47 deletions

View File

@ -24,6 +24,11 @@ public class AutoApplicableConverterDescriptorBypassedImpl implements AutoApplic
private AutoApplicableConverterDescriptorBypassedImpl() {
}
@Override
public boolean isAutoApplicable() {
return false;
}
@Override
public ConverterDescriptor getAutoAppliedConverterDescriptorForAttribute(
MemberDetails memberDetails,

View File

@ -33,6 +33,11 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
this.linkedConverterDescriptor = linkedConverterDescriptor;
}
@Override
public boolean isAutoApplicable() {
return true;
}
@Override
public ConverterDescriptor getAutoAppliedConverterDescriptorForAttribute(
MemberDetails memberDetails,
@ -51,16 +56,16 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
final ResolvedMember<?> collectionMember = resolveMember( memberDetails, context );
final ResolvedType elementType;
Class<?> erasedType = collectionMember.getType().getErasedType();
final Class<?> erasedType = collectionMember.getType().getErasedType();
if ( Map.class.isAssignableFrom( erasedType ) ) {
List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Map.class);
final List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Map.class);
if ( typeArguments.size() < 2 ) {
return null;
}
elementType = typeArguments.get( 1 );
}
else if ( Collection.class.isAssignableFrom( erasedType ) ) {
List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Collection.class);
final List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Collection.class);
if ( typeArguments.isEmpty() ) {
return null;
}
@ -87,7 +92,7 @@ public class AutoApplicableConverterDescriptorStandardImpl implements AutoApplic
final ResolvedType keyType;
if ( Map.class.isAssignableFrom( collectionMember.getType().getErasedType() ) ) {
List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Map.class);
final List<ResolvedType> typeArguments = collectionMember.getType().typeParametersFor(Map.class);
if ( typeArguments.isEmpty() ) {
return null;
}

View File

@ -13,6 +13,7 @@ import org.hibernate.models.spi.MemberDetails;
* @author Steve Ebersole
*/
public interface AutoApplicableConverterDescriptor {
boolean isAutoApplicable();
ConverterDescriptor getAutoAppliedConverterDescriptorForAttribute(MemberDetails memberDetails, MetadataBuildingContext context);
ConverterDescriptor getAutoAppliedConverterDescriptorForCollectionElement(MemberDetails memberDetails, MetadataBuildingContext context);
ConverterDescriptor getAutoAppliedConverterDescriptorForMapKey(MemberDetails memberDetails, MetadataBuildingContext context);

View File

@ -87,7 +87,7 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
@Override
public ConverterDescriptor resolveAttributeConverterDescriptor(MemberDetails attributeMember) {
AttributeConversionInfo info = locateAttributeConversionInfo( attributeMember );
final AttributeConversionInfo info = locateAttributeConversionInfo( attributeMember );
if ( info != null ) {
if ( info.isConversionDisabled() ) {
return null;

View File

@ -12,6 +12,7 @@ import java.util.Map;
import java.util.function.Function;
import jakarta.persistence.Embedded;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
@ -20,35 +21,7 @@ import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.AnyDiscriminator;
import org.hibernate.annotations.AnyKeyJavaClass;
import org.hibernate.annotations.AnyKeyJavaType;
import org.hibernate.annotations.AnyKeyJdbcType;
import org.hibernate.annotations.AnyKeyJdbcTypeCode;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionIdJavaType;
import org.hibernate.annotations.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionIdMutability;
import org.hibernate.annotations.CollectionIdType;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.ListIndexJavaType;
import org.hibernate.annotations.ListIndexJdbcType;
import org.hibernate.annotations.ListIndexJdbcTypeCode;
import org.hibernate.annotations.MapKeyJavaType;
import org.hibernate.annotations.MapKeyJdbcType;
import org.hibernate.annotations.MapKeyJdbcTypeCode;
import org.hibernate.annotations.MapKeyMutability;
import org.hibernate.annotations.MapKeyType;
import org.hibernate.annotations.Mutability;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.TimeZoneColumn;
import org.hibernate.annotations.TimeZoneStorage;
import org.hibernate.annotations.TimeZoneStorageType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.*;
import org.hibernate.boot.internal.AnyKeyType;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.boot.spi.AccessType;
@ -1188,30 +1161,43 @@ public class BasicValueBinder implements JdbcTypeIndicators {
}
private void applyJpaConverter(MemberDetails attribute, ConverterDescriptor attributeConverterDescriptor) {
disallowConverter( attribute, Id.class );
disallowConverter( attribute, Version.class );
final boolean autoApply = attributeConverterDescriptor.getAutoApplyDescriptor().isAutoApplicable();
disallowConverter( attribute, Id.class, autoApply );
disallowConverter( attribute, Version.class, autoApply );
if ( kind == Kind.MAP_KEY ) {
//noinspection deprecation
disallowConverter( attribute, MapKeyTemporal.class );
disallowConverter( attribute, MapKeyEnumerated.class );
disallowConverter( attribute, MapKeyTemporal.class, autoApply );
disallowConverter( attribute, MapKeyEnumerated.class, autoApply );
}
else {
//noinspection deprecation
disallowConverter( attribute, Temporal.class );
disallowConverter( attribute, Enumerated.class );
disallowConverter( attribute, Embedded.class );
disallowConverter( attribute, ManyToOne.class );
disallowConverter( attribute, OneToOne.class );
disallowConverter( attribute, OneToMany.class );
disallowConverter( attribute, ManyToMany.class );
disallowConverter( attribute, Temporal.class, autoApply );
disallowConverter( attribute, Enumerated.class, autoApply );
disallowConverter( attribute, ManyToOne.class, autoApply );
disallowConverter( attribute, OneToOne.class, autoApply );
disallowConverter( attribute, OneToMany.class, autoApply );
disallowConverter( attribute, ManyToMany.class, autoApply );
// Note that @Convert is only allowed in conjunction with
// @Embedded if it specifies a field using attributeName
disallowConverter( attribute, Embedded.class, autoApply );
disallowConverter( attribute, EmbeddedId.class, autoApply );
}
// I assume that these do not work with converters (no tests)
disallowConverter( attribute, Struct.class, autoApply );
disallowConverter( attribute, Array.class, autoApply );
disallowConverter( attribute, Any.class, autoApply );
this.converterDescriptor = attributeConverterDescriptor;
}
void disallowConverter(MemberDetails attribute, Class<? extends Annotation> annotationType) {
void disallowConverter(MemberDetails attribute, Class<? extends Annotation> annotationType, boolean autoApply) {
// NOTE: A really faithful reading of the JPA spec is that we should
// just silently ignore any auto-apply converter which matches
// one of the disallowed attribute types, but for now let's be
// a bit more fussy/helpful, and see how many people complain.
if ( attribute.hasDirectAnnotationUsage( annotationType ) ) {
throw new AnnotationException( "'AttributeConverter' not allowed for attribute '" + attribute.getName()
+ "' annotated '@" + annotationType.getName() + "'" );
+ "' annotated '@" + annotationType.getName() + "'"
+ ( autoApply ? " (use '@Convert(disableConversion=true)' to suppress this error)" : "" ) );
}
}