Skip to content

Commit bbfba45

Browse files
committed
HHH-19757 fix operations with unbound type parameters
Many operations of TypeConfiguration, BasicTypeRegistry, JavaTypeRegistry were unsafe due to the use of an unbound type parameter in the return type. Note that this is in principle a breaking change to these SPIs. However, I've done it in a way that minimizes the impact on reasonable code.
1 parent dd6a724 commit bbfba45

File tree

14 files changed

+217
-175
lines changed

14 files changed

+217
-175
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ default void contributeAttributeConverter(Class<? extends AttributeConverter<?,
8989
default void contributeType(BasicType<?> type) {
9090
getTypeConfiguration().getBasicTypeRegistry().register( type );
9191
final JavaType<?> javaType = type.getJavaTypeDescriptor();
92-
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType );
92+
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType );
9393
}
9494

9595
/**
@@ -99,7 +99,7 @@ default void contributeType(BasicType<?> type) {
9999
default void contributeType(BasicType<?> type, String... keys) {
100100
getTypeConfiguration().getBasicTypeRegistry().register( type, keys );
101101
final JavaType<?> javaType = type.getJavaTypeDescriptor();
102-
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType );
102+
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType );
103103
}
104104

105105
/**
@@ -109,6 +109,6 @@ default void contributeType(BasicType<?> type, String... keys) {
109109
default void contributeType(UserType<?> type, String... keys) {
110110
final CustomType<?> customType = getTypeConfiguration().getBasicTypeRegistry().register( type, keys );
111111
final JavaType<?> javaType = customType.getJavaTypeDescriptor();
112-
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType );
112+
getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType );
113113
}
114114
}

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentBinder.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.hibernate.models.spi.MemberDetails;
1919
import org.hibernate.type.SqlTypes;
2020
import org.hibernate.type.descriptor.java.spi.EmbeddableAggregateJavaType;
21+
import org.hibernate.type.spi.TypeConfiguration;
2122

2223
import static org.hibernate.boot.model.internal.BasicValueBinder.Kind.ATTRIBUTE;
2324

@@ -45,10 +46,7 @@ public static void processAggregate(
4546
final String structName = structQualifiedName == null ? null : structQualifiedName.render();
4647

4748
// We must register a special JavaType for the embeddable which can provide a recommended JdbcType
48-
typeConfiguration.getJavaTypeRegistry().resolveDescriptor(
49-
component.getComponentClass(),
50-
() -> new EmbeddableAggregateJavaType<>( component.getComponentClass(), structName )
51-
);
49+
registerDescriptor( component.getComponentClass(), typeConfiguration, structName );
5250
component.setStructName( structQualifiedName );
5351
component.setStructColumnNames( determineStructAttributeNames( inferredData, componentClassDetails ) );
5452

@@ -98,6 +96,12 @@ public static void processAggregate(
9896
}
9997
}
10098

99+
private static <T> void registerDescriptor(Class<T> componentClass, TypeConfiguration typeConfiguration, String structName) {
100+
typeConfiguration.getJavaTypeRegistry()
101+
.resolveDescriptor( componentClass,
102+
() -> new EmbeddableAggregateJavaType<>( componentClass, structName ) );
103+
}
104+
101105
private static int getStructPluralSqlTypeCode(MetadataBuildingContext context) {
102106
return switch ( context.getPreferredSqlTypeCodeForArray() ) {
103107
case SqlTypes.ARRAY -> SqlTypes.STRUCT_ARRAY;

hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.hibernate.metamodel.UnsupportedMappingException;
3030
import org.hibernate.metamodel.ValueClassification;
3131
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
32+
import org.hibernate.metamodel.mapping.DiscriminatorType;
3233
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
3334
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
3435
import org.hibernate.metamodel.model.domain.internal.AbstractIdentifiableType;
@@ -237,17 +238,14 @@ private static EmbeddableDomainType<?> classEmbeddableType(MetadataContext conte
237238
}
238239

239240
final var mappedSuperclass = component.getMappedSuperclass();
240-
final var superType = mappedSuperclass == null ? null : context.locateMappedSuperclassType( mappedSuperclass );
241+
final var superType =
242+
mappedSuperclass == null
243+
? null
244+
: context.locateMappedSuperclassType( mappedSuperclass );
241245

242246
final var discriminatorType = component.isPolymorphic() ? component.getDiscriminatorType() : null;
243247

244-
final var embeddableType = new EmbeddableTypeImpl<>(
245-
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( embeddableClass ),
246-
superType,
247-
discriminatorType,
248-
false,
249-
context.getJpaMetamodel()
250-
);
248+
final var embeddableType = embeddableType( context, embeddableClass, superType, discriminatorType );
251249
context.registerEmbeddableType( embeddableType, component );
252250

253251
if ( component.isPolymorphic() ) {
@@ -259,24 +257,36 @@ private static EmbeddableDomainType<?> classEmbeddableType(MetadataContext conte
259257
for ( final String subclassName : embeddableSubclasses ) {
260258
if ( domainTypes.containsKey( subclassName ) ) {
261259
assert subclassName.equals( embeddableType.getTypeName() );
262-
continue;
263260
}
264-
final Class<?> subclass = classLoaderService.classForName( subclassName );
265-
final var subType = new EmbeddableTypeImpl<>(
266-
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( subclass ),
267-
domainTypes.get( component.getSuperclass( subclassName ) ),
268-
discriminatorType,
269-
false,
270-
context.getJpaMetamodel()
271-
);
272-
domainTypes.put( subclassName, subType );
273-
context.registerEmbeddableType( subType, component );
261+
else {
262+
final Class<?> subclass = classLoaderService.classForName( subclassName );
263+
final var superTypeEmbeddable = domainTypes.get( component.getSuperclass( subclassName ) );
264+
final var subType = embeddableType( context, subclass, superTypeEmbeddable, discriminatorType );
265+
domainTypes.put( subclassName, subType );
266+
context.registerEmbeddableType( subType, component );
267+
}
274268
}
275269
}
276270

277271
return embeddableType;
278272
}
279273

274+
private static <J> EmbeddableTypeImpl<J> embeddableType(
275+
MetadataContext context,
276+
Class<J> subclass,
277+
ManagedDomainType<?> superType,
278+
DiscriminatorType<?> discriminatorType) {
279+
@SuppressWarnings("unchecked")
280+
final var castSuperType = (ManagedDomainType<? super J>) superType;
281+
return new EmbeddableTypeImpl<>(
282+
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( subclass ),
283+
castSuperType,
284+
discriminatorType,
285+
false,
286+
context.getJpaMetamodel()
287+
);
288+
}
289+
280290
private static EmbeddableTypeImpl<?> dynamicEmbeddableType(MetadataContext context, Component component) {
281291
final var embeddableType = new EmbeddableTypeImpl<>(
282292
context.getJavaTypeRegistry().resolveDescriptor( java.util.Map.class ),

hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyPojo.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,8 @@ private static <T> JavaType<T> resolveEmbeddableJavaType(
131131
return javaTypeRegistry.getDescriptor( bootDescriptor.getComponentClass() );
132132
}
133133
else {
134-
return javaTypeRegistry.resolveDescriptor(
135-
compositeUserType.returnedClass(),
136-
() -> new CompositeUserTypeJavaTypeWrapper<>( compositeUserType )
137-
);
134+
return javaTypeRegistry.resolveDescriptor( compositeUserType.returnedClass(),
135+
() -> new CompositeUserTypeJavaTypeWrapper<>( compositeUserType ) );
138136
}
139137
}
140138

hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -577,19 +577,22 @@ private Property getMappedSuperclassIdentifier(PersistentClass persistentClass)
577577
return null;
578578
}
579579

580-
private <Y> EmbeddableTypeImpl<Y> applyIdClassMetadata(Component idClassComponent) {
581-
final var embeddableType =
582-
new EmbeddableTypeImpl<Y>(
583-
getJavaTypeRegistry().resolveManagedTypeDescriptor( idClassComponent.getComponentClass() ),
584-
getMappedSuperclassDomainType( idClassComponent ),
585-
null,
586-
false,
587-
getJpaMetamodel()
588-
);
580+
private EmbeddableTypeImpl<?> applyIdClassMetadata(Component idClassComponent) {
581+
final var embeddableType = embeddableType( idClassComponent, idClassComponent.getComponentClass() );
589582
registerEmbeddableType( embeddableType, idClassComponent );
590583
return embeddableType;
591584
}
592585

586+
private <Y> EmbeddableTypeImpl<Y> embeddableType(Component idClassComponent, Class<Y> componentClass) {
587+
return new EmbeddableTypeImpl<>(
588+
getJavaTypeRegistry().resolveManagedTypeDescriptor( componentClass ),
589+
getMappedSuperclassDomainType( idClassComponent ),
590+
null,
591+
false,
592+
getJpaMetamodel()
593+
);
594+
}
595+
593596
@SuppressWarnings("unchecked")
594597
private <Y> MappedSuperclassDomainType<? super Y> getMappedSuperclassDomainType(Component idClassComponent) {
595598
final MappedSuperclass mappedSuperclass = idClassComponent.getMappedSuperclass();

hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ public void processJpa(
621621
);
622622

623623

624-
for ( PersistentClass entityBinding : bootMetamodel.getEntityBindings() ) {
624+
for ( var entityBinding : bootMetamodel.getEntityBindings() ) {
625625
locateOrBuildEntityType( entityBinding, context, typeConfiguration );
626626
}
627627
handleUnusedMappedSuperclasses( context, typeConfiguration );
@@ -719,47 +719,47 @@ public static void addAllowedEnumLiteralsToEnumTypesMap(
719719
.add( enumClassName );
720720
}
721721

722-
private <T> EntityDomainType<T> locateOrBuildEntityType(
722+
private EntityDomainType<?> locateOrBuildEntityType(
723723
PersistentClass persistentClass,
724724
MetadataContext context,
725725
final TypeConfiguration typeConfiguration) {
726-
@SuppressWarnings("unchecked")
727-
final EntityDomainType<T> entityType =
728-
(EntityDomainType<T>)
729-
context.locateEntityType( persistentClass );
726+
final var entityType = context.locateEntityType( persistentClass );
730727
return entityType == null
731728
? buildEntityType( persistentClass, context, typeConfiguration )
732729
: entityType;
733730
}
734731

735-
private <T> EntityTypeImpl<T> buildEntityType(
732+
private EntityTypeImpl<?> buildEntityType(
736733
PersistentClass persistentClass,
737734
MetadataContext context,
738735
TypeConfiguration typeConfiguration) {
739736
context.pushEntityWorkedOn( persistentClass );
740-
final EntityTypeImpl<T> entityType =
741-
new EntityTypeImpl<>(
742-
javaType( persistentClass, context ),
743-
supertypeForPersistentClass( persistentClass, context, typeConfiguration ),
744-
persistentClass,
745-
this
746-
);
737+
final var entityType = entityType( persistentClass, persistentClass.getMappedClass(), context, typeConfiguration );
747738
context.registerEntityType( persistentClass, entityType );
748739
context.popEntityWorkedOn( persistentClass );
749740
return entityType;
750741
}
751742

752-
@SuppressWarnings("unchecked")
753-
private static <T> JavaType<T> javaType(PersistentClass persistentClass, MetadataContext context) {
754-
final Class<T> javaTypeClass = (Class<T>) persistentClass.getMappedClass();
755-
if ( javaTypeClass == null || Map.class.isAssignableFrom( javaTypeClass ) ) {
743+
private <J> EntityTypeImpl<J> entityType(
744+
PersistentClass persistentClass,
745+
Class<J> mappedClass,
746+
MetadataContext context,
747+
TypeConfiguration typeConfiguration) {
748+
@SuppressWarnings("unchecked")
749+
final var supertype =
750+
(IdentifiableDomainType<? super J>)
751+
supertypeForPersistentClass( persistentClass, context, typeConfiguration );
752+
final JavaType<J> javaType;
753+
if ( mappedClass == null || Map.class.isAssignableFrom( mappedClass ) ) {
756754
// dynamic map
757-
return (JavaType<T>) new DynamicModelJavaType();
755+
//noinspection unchecked
756+
javaType = (JavaType<J>) new DynamicModelJavaType();
758757
}
759758
else {
760-
return context.getTypeConfiguration().getJavaTypeRegistry()
761-
.resolveEntityTypeDescriptor( javaTypeClass );
759+
javaType = context.getTypeConfiguration().getJavaTypeRegistry()
760+
.resolveEntityTypeDescriptor( mappedClass );
762761
}
762+
return new EntityTypeImpl<>( javaType, supertype, persistentClass, this );
763763
}
764764

765765
private void handleUnusedMappedSuperclasses(MetadataContext context, TypeConfiguration typeConfiguration) {
@@ -772,39 +772,41 @@ private void handleUnusedMappedSuperclasses(MetadataContext context, TypeConfigu
772772
}
773773
}
774774

775-
private <T> MappedSuperclassDomainType<T> locateOrBuildMappedSuperclassType(
775+
private MappedSuperclassDomainType<?> locateOrBuildMappedSuperclassType(
776776
MappedSuperclass mappedSuperclass,
777777
MetadataContext context,
778778
TypeConfiguration typeConfiguration) {
779-
@SuppressWarnings("unchecked")
780-
final MappedSuperclassDomainType<T> mappedSuperclassType =
781-
(MappedSuperclassDomainType<T>) context.locateMappedSuperclassType( mappedSuperclass );
779+
final MappedSuperclassDomainType<?> mappedSuperclassType =
780+
context.locateMappedSuperclassType( mappedSuperclass );
782781
return mappedSuperclassType == null
783-
? buildMappedSuperclassType( mappedSuperclass, context, typeConfiguration )
782+
? buildMappedSuperclassType( mappedSuperclass, mappedSuperclass.getMappedClass(), context, typeConfiguration )
784783
: mappedSuperclassType;
785784
}
786785

787786
private <T> MappedSuperclassTypeImpl<T> buildMappedSuperclassType(
788787
MappedSuperclass mappedSuperclass,
788+
Class<T> mappedClass,
789789
MetadataContext context,
790790
TypeConfiguration typeConfiguration) {
791+
@SuppressWarnings("unchecked")
791792
final IdentifiableDomainType<? super T> superType =
792-
supertypeForMappedSuperclass( mappedSuperclass, context, typeConfiguration );
793+
(IdentifiableDomainType<? super T>)
794+
supertypeForMappedSuperclass( mappedSuperclass, context, typeConfiguration );
793795
final JavaType<T> javaType =
794796
context.getTypeConfiguration().getJavaTypeRegistry()
795-
.resolveManagedTypeDescriptor( mappedSuperclass.getMappedClass() );
797+
.resolveManagedTypeDescriptor( mappedClass );
796798
final MappedSuperclassTypeImpl<T> mappedSuperclassType =
797799
new MappedSuperclassTypeImpl<>( javaType, mappedSuperclass, superType, this );
798800
context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType );
799801
return mappedSuperclassType;
800802
}
801803

802-
private <T> IdentifiableDomainType<? super T> supertypeForPersistentClass(
804+
private IdentifiableDomainType<?> supertypeForPersistentClass(
803805
PersistentClass persistentClass,
804806
MetadataContext context,
805807
TypeConfiguration typeConfiguration) {
806808
final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass();
807-
final IdentifiableDomainType<? super T> supertype =
809+
final IdentifiableDomainType<?> supertype =
808810
superMappedSuperclass == null
809811
? null
810812
: locateOrBuildMappedSuperclassType( superMappedSuperclass, context, typeConfiguration );
@@ -821,12 +823,12 @@ private <T> IdentifiableDomainType<? super T> supertypeForPersistentClass(
821823
}
822824
}
823825

824-
private <T> IdentifiableDomainType<? super T> supertypeForMappedSuperclass(
826+
private IdentifiableDomainType<?> supertypeForMappedSuperclass(
825827
MappedSuperclass mappedSuperclass,
826828
MetadataContext context,
827829
TypeConfiguration typeConfiguration) {
828830
final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass();
829-
final IdentifiableDomainType<T> superType =
831+
final IdentifiableDomainType<?> superType =
830832
superMappedSuperclass == null
831833
? null
832834
: locateOrBuildMappedSuperclassType( superMappedSuperclass, context, typeConfiguration );

hibernate-core/src/main/java/org/hibernate/query/hql/internal/FullyQualifiedReflectivePathTerminal.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ private SqmExpression createEnumOrFieldLiteral(Class namedClass) throws NoSuchFi
116116
if ( namedClass.isEnum() ) {
117117
return new SqmEnumLiteral(
118118
Enum.valueOf( namedClass, getLocalName() ),
119-
(EnumJavaType) javaTypeRegistry()
120-
.resolveDescriptor( namedClass, () -> new EnumJavaType( namedClass ) ),
119+
(EnumJavaType)
120+
javaTypeRegistry()
121+
.resolveDescriptor( namedClass, () -> new EnumJavaType( namedClass ) ),
121122
getLocalName(),
122123
nodeBuilder()
123124
);

hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ private void bindNull(boolean resolveJdbcTypeIfNecessary) {
134134
isBound = true;
135135
bindValue = null;
136136
if ( resolveJdbcTypeIfNecessary && bindType == null ) {
137-
bindType = getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( "null" );
137+
bindType = (BindableType<? super T>)
138+
getTypeConfiguration().getBasicTypeRegistry()
139+
.getRegisteredType( "null" );
138140
}
139141
}
140142

0 commit comments

Comments
 (0)