HHH-14660 Deprecate component mappings with different attributes for the same class

This commit is contained in:
Christian Beikov 2021-06-09 18:15:05 +02:00
parent 916bcbdef0
commit d60dc9255d
3 changed files with 79 additions and 35 deletions

View File

@ -250,4 +250,12 @@ public interface DeprecationLogger extends BasicLogger {
"5.3 in upgrading. It will be removed in a later version."
)
void logUseOfDeprecatedZeroBasedJdbcStyleParams();
@LogMessage(level = WARN)
@Message(
id = 90000025,
value = "Encountered multiple component mappings for the same java class [%s] with different property mappings. " +
"This is deprecated and will be removed in a future version. Every property mapping combination should have its own java class"
)
void deprecatedComponentMapping(String name);
}

View File

@ -102,34 +102,40 @@ public class AttributeFactory {
if ( attributeContext.getPropertyMapping().getType().isComponentType() && jpaAttributeNature.equals( Attribute.PersistentAttributeType.BASIC ) ) {
CompositeType compositeType = (CompositeType) attributeContext.getPropertyMapping().getType();
EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<>(
attributeMetadata.getJavaType(),
ownerType,
compositeType,
context.getSessionFactory()
);
context.registerEmbeddedableType(embeddableType);
String[] propertyNames = compositeType.getPropertyNames();
org.hibernate.type.Type[] subtypes = compositeType.getSubtypes();
InFlightAccess<?> inFlightAccess = embeddableType.getInFlightAccess();
for ( int i = 0; i < propertyNames.length; i++ ) {
SingularAttributeImpl nestedAttribute = new SingularAttributeImpl(
embeddableType,
propertyNames[i],
Attribute.PersistentAttributeType.BASIC,
new BasicTypeImpl<Object>(subtypes[i].getReturnedClass(), Type.PersistenceType.BASIC),
null,
false,
false,
property.isOptional()
);
inFlightAccess.addAttribute(nestedAttribute);
}
metaModelType = embeddableType;
metaModelType = context.locateEmbeddable( attributeMetadata.getJavaType(), compositeType );
jpaAttributeNature = Attribute.PersistentAttributeType.EMBEDDED;
if ( metaModelType == null ) {
metaModelType = context.locateEmbeddable( attributeMetadata.getJavaType(), compositeType );
if ( metaModelType == null ) {
EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<>(
attributeMetadata.getJavaType(),
ownerType,
compositeType,
context.getSessionFactory()
);
context.registerEmbeddableType( embeddableType, compositeType );
String[] propertyNames = compositeType.getPropertyNames();
org.hibernate.type.Type[] subtypes = compositeType.getSubtypes();
InFlightAccess<?> inFlightAccess = embeddableType.getInFlightAccess();
for (int i = 0; i < propertyNames.length; i++) {
SingularAttributeImpl nestedAttribute = new SingularAttributeImpl(
embeddableType,
propertyNames[i],
Attribute.PersistentAttributeType.BASIC,
new BasicTypeImpl<Object>( subtypes[i].getReturnedClass(), Type.PersistenceType.BASIC ),
null,
false,
false,
property.isOptional()
);
inFlightAccess.addAttribute( nestedAttribute );
}
metaModelType = embeddableType;
}
}
}
return new SingularAttributeImpl(
@ -249,13 +255,17 @@ public class AttributeFactory {
}
case EMBEDDABLE: {
final Component component = (Component) typeContext.getHibernateValue();
final CompositeType compositeType = (CompositeType) component.getType();
Class javaType;
if ( component.getComponentClassName() == null ) {
javaType = typeContext.getJpaBindableType();
}
else {
javaType = component.getComponentClass();
final EmbeddedTypeDescriptor<Y> cached = context.locateEmbeddable( javaType, compositeType );
if ( cached != null ) {
return cached;
}
}
final EmbeddedTypeDescriptor<Y> embeddableType = new EmbeddableTypeImpl<Y>(
@ -264,7 +274,7 @@ public class AttributeFactory {
(ComponentType) typeContext.getHibernateValue().getType(),
context.getSessionFactory()
);
context.registerEmbeddedableType( embeddableType );
context.registerEmbeddableType( embeddableType, compositeType );
final InFlightAccess<Y> inFlightAccess = embeddableType.getInFlightAccess();
final Iterator<Property> subProperties = component.getPropertyIterator();

View File

@ -8,6 +8,7 @@ package org.hibernate.metamodel.internal;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -25,6 +26,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Component;
@ -42,6 +44,7 @@ import org.hibernate.metamodel.model.domain.spi.IdentifiableTypeDescriptor;
import org.hibernate.metamodel.model.domain.spi.ManagedTypeDescriptor;
import org.hibernate.metamodel.model.domain.spi.MappedSuperclassTypeDescriptor;
import org.hibernate.metamodel.model.domain.spi.SingularPersistentAttribute;
import org.hibernate.type.CompositeType;
/**
* Defines a context for storing information during the building of the {@link MetamodelImpl}.
@ -51,7 +54,7 @@ import org.hibernate.metamodel.model.domain.spi.SingularPersistentAttribute;
* <p/>
* At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeSet}
* results, which represent all the registered {@linkplain #registerEntityType entities} and
* {@linkplain #registerEmbeddedableType embeddables} respectively.
* {@linkplain #registerEmbeddableType embeddables} respectively.
*
* @author Steve Ebersole
* @author Emmanuel Bernard
@ -68,7 +71,8 @@ class MetadataContext {
private Map<String, EntityTypeDescriptor<?>> entityTypesByEntityName = new HashMap<>();
private Map<PersistentClass, EntityTypeDescriptor<?>> entityTypesByPersistentClass = new HashMap<>();
private Set<EmbeddedTypeDescriptor<?>> embeddables = new HashSet<>();
private Map<Class, List<EmbeddedTypeDescriptor<?>>> embeddablesToProcess = new HashMap<>();
private Map<EmbeddedTypeDescriptor<?>, CompositeType> componentByEmbeddable = new HashMap<>();
private Map<MappedSuperclass, MappedSuperclassTypeDescriptor<?>> mappedSuperclassByMappedSuperclassMapping = new HashMap<>();
private Map<MappedSuperclassTypeDescriptor<?>, PersistentClass> mappedSuperClassTypeToPersistentClass = new HashMap<>();
@ -108,7 +112,7 @@ class MetadataContext {
}
public Set<EmbeddedTypeDescriptor<?>> getEmbeddableTypeSet() {
return Collections.unmodifiableSet( embeddables );
return Collections.unmodifiableSet( componentByEmbeddable.keySet() );
}
public Map<Class<?>, MappedSuperclassType<?>> getMappedSuperclassTypeMap() {
@ -141,9 +145,13 @@ class MetadataContext {
orderedMappings.add( persistentClass );
}
/*package*/ void registerEmbeddedableType(EmbeddedTypeDescriptor<?> embeddableType) {
/*package*/ void registerEmbeddableType(EmbeddedTypeDescriptor<?> embeddableType, CompositeType component) {
final List<EmbeddedTypeDescriptor<?>> existingEmbeddables = embeddablesToProcess.computeIfAbsent(
embeddableType.getJavaType(), k -> new ArrayList<>( 1 )
);
existingEmbeddables.add( embeddableType );
if ( !( ignoreUnsupported && embeddableType.getParent().getJavaType() == null ) ) {
embeddables.add( embeddableType );
componentByEmbeddable.put( embeddableType, component );
}
}
@ -198,6 +206,24 @@ class MetadataContext {
return Collections.unmodifiableMap( entityTypesByEntityName );
}
public <J> EmbeddedTypeDescriptor<J> locateEmbeddable(Class<J> embeddableClass, CompositeType component) {
final List<EmbeddedTypeDescriptor<?>> embeddableDomainTypes = embeddablesToProcess.get( embeddableClass );
if ( embeddableDomainTypes != null ) {
for ( EmbeddedTypeDescriptor<?> embeddableDomainType : embeddableDomainTypes ) {
final CompositeType cachedComponent = componentByEmbeddable.get( embeddableDomainType );
if ( Arrays.equals( cachedComponent.getPropertyNames(), component.getPropertyNames() ) ) {
//noinspection unchecked
return (EmbeddedTypeDescriptor<J>) embeddableDomainType;
}
else {
// See HHH-14660
DeprecationLogger.DEPRECATION_LOGGER.deprecatedComponentMapping(embeddableClass.getName() );
}
}
}
return null;
}
@SuppressWarnings({"unchecked"})
public void wrapUp() {
if ( LOG.isTraceEnabled() ) {
@ -294,7 +320,7 @@ class MetadataContext {
}
if ( staticMetamodelScanEnabled ) {
for ( EmbeddedTypeDescriptor embeddable : embeddables ) {
for ( EmbeddedTypeDescriptor embeddable : componentByEmbeddable.keySet() ) {
populateStaticMetamodel( embeddable );
}
}