diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index b79e372445..3419f3a25e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -11,10 +11,6 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.Iterator; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.OneToOne; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.Type; import org.hibernate.AssertionFailure; import org.hibernate.internal.EntityManagerMessageLogger; @@ -29,6 +25,7 @@ import org.hibernate.mapping.Property; import org.hibernate.mapping.Value; import org.hibernate.metamodel.AttributeClassification; import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; @@ -52,6 +49,12 @@ import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; +import org.hibernate.type.spi.CompositeTypeImplementor; + +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.Type; /** * A factory for building {@link Attribute} instances. Exposes 3 main services for building
    @@ -231,21 +234,16 @@ public class AttributeFactory { final Component component = (Component) typeContext.getHibernateValue(); final EmbeddableTypeImpl embeddableType; - final EmbeddableRepresentationStrategy representationStrategy = context.getTypeConfiguration() - .getMetadataBuildingContext() - .getBuildingOptions() - .getManagedTypeRepresentationResolver() - .resolveStrategy( component, context.getRuntimeModelCreationContext() ); - if ( component.isDynamic() ) { final JavaType javaTypeDescriptor = context.getJavaTypeDescriptorRegistry().getDescriptor( Map.class ); embeddableType = new EmbeddableTypeImpl<>( javaTypeDescriptor, - representationStrategy, true, context.getJpaMetamodel() ); + + context.registerComponentByEmbeddable( embeddableType, component ); } else { // we should have a non-dynamic embeddable @@ -263,7 +261,6 @@ public class AttributeFactory { embeddableType = new EmbeddableTypeImpl<>( javaTypeDescriptor, - representationStrategy, false, context.getJpaMetamodel() ); @@ -585,16 +582,23 @@ public class AttributeFactory { private static final MemberResolver embeddedMemberResolver = (attributeContext, metadataContext) -> { // the owner is an embeddable - final EmbeddableDomainType ownerType = (EmbeddableDomainType) attributeContext.getOwnerType(); + final EmbeddableDomainType ownerType = (EmbeddableDomainType) attributeContext.getOwnerType(); + final Component ownerBootDescriptor = metadataContext.getEmbeddableBootDescriptor( ownerType ); - if ( ownerType.getRepresentationStrategy().getMode() == RepresentationMode.MAP ) { + final CompositeTypeImplementor ownerComponentType = (CompositeTypeImplementor) ownerBootDescriptor.getType(); + final EmbeddableValuedModelPart ownerMappingModelDescriptor = ownerComponentType.getMappingModelPart(); + final EmbeddableRepresentationStrategy ownerRepStrategy = ownerMappingModelDescriptor + .getEmbeddableTypeDescriptor() + .getRepresentationStrategy(); + + if ( ownerRepStrategy.getMode() == RepresentationMode.MAP ) { return new MapMember( attributeContext.getPropertyMapping().getName(), attributeContext.getPropertyMapping().getType().getReturnedClass() ); } else { - return ownerType.getRepresentationStrategy() + return ownerRepStrategy .resolvePropertyAccess( attributeContext.getPropertyMapping() ) .getGetter() .getMember(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorDynamicMap.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorDynamicMap.java index d20ab5e964..8167c3004d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorDynamicMap.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorDynamicMap.java @@ -6,10 +6,12 @@ */ package org.hibernate.metamodel.internal; +import java.util.Map; import java.util.function.Supplier; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Component; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.spi.EmbeddableInstantiator; /** @@ -20,12 +22,24 @@ import org.hibernate.metamodel.spi.EmbeddableInstantiator; public class EmbeddableInstantiatorDynamicMap extends AbstractDynamicMapInstantiator implements EmbeddableInstantiator { - public EmbeddableInstantiatorDynamicMap(Component bootDescriptor) { + private final Supplier runtimeDescriptorAccess; + + public EmbeddableInstantiatorDynamicMap( + Component bootDescriptor, + Supplier runtimeDescriptorAccess) { super( bootDescriptor.getRoleName() ); + this.runtimeDescriptorAccess = runtimeDescriptorAccess; } @Override public Object instantiate(Supplier valuesAccess, SessionFactoryImplementor sessionFactory) { - return generateDataMap(); + final Map dataMap = generateDataMap(); + + if ( valuesAccess != null ) { + final EmbeddableMappingType mappingType = runtimeDescriptorAccess.get(); + mappingType.setPropertyValues( dataMap, valuesAccess.get() ); + } + + return dataMap; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoStandard.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoStandard.java index 7cfa7f58fc..451a691736 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoStandard.java @@ -10,12 +10,13 @@ import java.lang.reflect.Constructor; import java.util.function.Supplier; import org.hibernate.InstantiationException; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.PropertyNotFoundException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.mapping.Component; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.type.descriptor.java.JavaType; @@ -27,16 +28,16 @@ import org.hibernate.type.descriptor.java.JavaType; public class EmbeddableInstantiatorPojoStandard extends AbstractPojoInstantiator implements EmbeddableInstantiator { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiatorImpl.class ); + private final Supplier embeddableMappingAccess; private final Constructor constructor; public EmbeddableInstantiatorPojoStandard( - @SuppressWarnings("unused") Component bootDescriptor, + Supplier embeddableMappingAccess, JavaType javaTypeDescriptor) { super( javaTypeDescriptor.getJavaTypeClass() ); - constructor = resolveConstructor( javaTypeDescriptor.getJavaTypeClass() ); - - // todo (6.0) : add support for constructor value injection + this.embeddableMappingAccess = embeddableMappingAccess; + this.constructor = resolveConstructor( javaTypeDescriptor.getJavaTypeClass() ); } protected static Constructor resolveConstructor(Class mappedPojoClass) { @@ -55,16 +56,27 @@ public class EmbeddableInstantiatorPojoStandard extends AbstractPojoInstantiator if ( isAbstract() ) { throw new InstantiationException( "Cannot instantiate abstract class or interface: ", getMappedPojoClass() ); } - else if ( constructor == null ) { + + if ( constructor == null ) { throw new InstantiationException( "No default constructor for embeddable: ", getMappedPojoClass() ); } - else { - try { - return constructor.newInstance( (Object[]) null ); + + if ( valuesAccess != null ) { + if ( constructor.getParameterTypes().length > 0 ) { + // constructor injection + throw new NotYetImplementedFor6Exception( "Constructor injection for embeddables not yet implemented" ); } - catch ( Exception e ) { - throw new InstantiationException( "Could not instantiate entity: ", getMappedPojoClass(), e ); + } + + try { + final Object instance = constructor.newInstance(); + if ( valuesAccess != null ) { + embeddableMappingAccess.get().setPropertyValues( instance, valuesAccess.get() ); } + return instance; + } + catch ( Exception e ) { + throw new InstantiationException( "Could not instantiate embeddable: ", getMappedPojoClass(), e ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyMap.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyMap.java index cd4e27c5c1..97380c61e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyMap.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyMap.java @@ -7,11 +7,13 @@ package org.hibernate.metamodel.internal; import java.util.Map; +import java.util.function.Supplier; import org.hibernate.bytecode.spi.ReflectionOptimizer; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; @@ -28,9 +30,10 @@ public class EmbeddableRepresentationStrategyMap implements EmbeddableRepresenta public EmbeddableRepresentationStrategyMap( Component bootDescriptor, + Supplier runtimeDescriptorAccess, RuntimeModelCreationContext creationContext) { this.mapJtd = creationContext.getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Map.class ); - this.instantiator = new EmbeddableInstantiatorDynamicMap( bootDescriptor ); + this.instantiator = new EmbeddableInstantiatorDynamicMap( bootDescriptor, runtimeDescriptorAccess ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyPojo.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyPojo.java index 9f845e66a7..b034141ec8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyPojo.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableRepresentationStrategyPojo.java @@ -7,6 +7,7 @@ package org.hibernate.metamodel.internal; import java.util.Locale; +import java.util.function.Supplier; import org.hibernate.HibernateException; import org.hibernate.boot.registry.selector.spi.StrategySelector; @@ -20,6 +21,7 @@ import org.hibernate.mapping.Component; import org.hibernate.mapping.IndexBackref; import org.hibernate.mapping.Property; import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl; @@ -39,6 +41,7 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr public EmbeddableRepresentationStrategyPojo( Component bootDescriptor, + Supplier runtimeDescriptorAccess, RuntimeModelCreationContext creationContext) { super( bootDescriptor, @@ -64,10 +67,10 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr false ); - this.instantiator = determineInstantiator( bootDescriptor ); + this.instantiator = determineInstantiator( runtimeDescriptorAccess ); } - private EmbeddableInstantiator determineInstantiator(Component bootDescriptor) { + private EmbeddableInstantiator determineInstantiator(Supplier runtimeDescriptorAccess) { if ( reflectionOptimizer != null && reflectionOptimizer.getInstantiationOptimizer() != null ) { final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer(); return new EmbeddableInstantiatorPojoOptimized( @@ -77,7 +80,7 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr } return new EmbeddableInstantiatorPojoStandard( - bootDescriptor, + runtimeDescriptorAccess, getEmbeddableJavaTypeDescriptor() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java index 86aee8493a..266894a061 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java @@ -54,6 +54,7 @@ import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.type.CompositeType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; +import org.hibernate.type.spi.CompositeTypeImplementor; /** * @author Steve Ebersole @@ -112,12 +113,14 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent if ( bootDescriptor.getIdentifierMapper() != null ) { mapsIdRepresentationStrategy = new EmbeddableRepresentationStrategyPojo( bootDescriptor.getIdentifierMapper(), + () -> ( ( CompositeTypeImplementor) bootDescriptor.getIdentifierMapper().getType() ).getMappingModelPart().getEmbeddableTypeDescriptor(), creationContext ); } else if ( bootDescriptorIdentifier != null ) { mapsIdRepresentationStrategy = new EmbeddableRepresentationStrategyPojo( (Component) bootDescriptorIdentifier, + () -> ( ( CompositeTypeImplementor) bootDescriptor.getIdentifierMapper().getType() ).getMappingModelPart().getEmbeddableTypeDescriptor(), creationContext ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManagedTypeRepresentationResolverStandard.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManagedTypeRepresentationResolverStandard.java index cb75415df1..e174a10f06 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManagedTypeRepresentationResolverStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ManagedTypeRepresentationResolverStandard.java @@ -7,9 +7,12 @@ package org.hibernate.metamodel.internal; +import java.util.function.Supplier; + import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.EntityRepresentationStrategy; import org.hibernate.metamodel.spi.ManagedTypeRepresentationResolver; @@ -58,6 +61,7 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep @Override public EmbeddableRepresentationStrategy resolveStrategy( Component bootDescriptor, + Supplier runtimeDescriptorAccess, RuntimeModelCreationContext creationContext) { // RepresentationMode representation = bootDescriptor.getExplicitRepresentationMode(); RepresentationMode representation = null; @@ -71,7 +75,7 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep } if ( representation == RepresentationMode.MAP ) { - return new EmbeddableRepresentationStrategyMap( bootDescriptor, creationContext ); + return new EmbeddableRepresentationStrategyMap( bootDescriptor, runtimeDescriptorAccess, creationContext ); } else { // todo (6.0) : fix this @@ -80,7 +84,7 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep // // instead, resolve ReflectionOptimizer once - here - and pass along to // StandardPojoRepresentationStrategy - return new EmbeddableRepresentationStrategyPojo( bootDescriptor, creationContext ); + return new EmbeddableRepresentationStrategyPojo( bootDescriptor, runtimeDescriptorAccess, creationContext ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java index 204b23d6d1..550136c525 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java @@ -15,14 +15,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.IdentifiableType; -import jakarta.persistence.metamodel.SingularAttribute; -import jakarta.persistence.metamodel.Type; import org.hibernate.AssertionFailure; import org.hibernate.Internal; import org.hibernate.MappingException; +import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; import org.hibernate.internal.util.ReflectHelper; @@ -48,12 +45,16 @@ import org.hibernate.metamodel.model.domain.internal.EmbeddableTypeImpl; import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl; -import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.IdentifiableType; +import jakarta.persistence.metamodel.SingularAttribute; +import jakarta.persistence.metamodel.Type; + /** * Defines a context for storing information during the building of the {@link MappingMetamodelImpl}. *

    @@ -101,15 +102,16 @@ public class MetadataContext { public MetadataContext( JpaMetamodel jpaMetamodel, - RuntimeModelCreationContext runtimeModelCreationContext, - Set mappedSuperclasses, - JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting) { + MappingMetamodel mappingMetamodel, + MetadataImplementor bootMetamodel, + JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting, + RuntimeModelCreationContext runtimeModelCreationContext) { this.jpaMetamodel = jpaMetamodel; - this.runtimeModelCreationContext = runtimeModelCreationContext; - this.metamodel = runtimeModelCreationContext.getSessionFactory().getMetamodel(); - this.knownMappedSuperclasses = mappedSuperclasses; + this.metamodel = mappingMetamodel; + this.knownMappedSuperclasses = bootMetamodel.getMappedSuperclassMappingsCopy(); this.typeConfiguration = runtimeModelCreationContext.getTypeConfiguration(); this.jpaStaticMetaModelPopulationSetting = jpaStaticMetaModelPopulationSetting; + this.runtimeModelCreationContext = runtimeModelCreationContext; } public RuntimeModelCreationContext getRuntimeModelCreationContext() { @@ -177,11 +179,22 @@ public class MetadataContext { assert embeddableType.getJavaType() != null; assert ! Map.class.isAssignableFrom( embeddableType.getJavaType() ); - embeddablesToProcess.computeIfAbsent( embeddableType.getJavaType(), k -> new ArrayList<>( 1 ) ) - .add( embeddableType ); + embeddablesToProcess + .computeIfAbsent( embeddableType.getJavaType(), k -> new ArrayList<>( 1 ) ) + .add( embeddableType ); + registerComponentByEmbeddable( embeddableType, bootDescriptor ); + } + + public void registerComponentByEmbeddable( + EmbeddableDomainType embeddableType, + Component bootDescriptor) { componentByEmbeddable.put( embeddableType, bootDescriptor ); } + public Component getEmbeddableBootDescriptor(EmbeddableDomainType embeddableType) { + return componentByEmbeddable.get( embeddableType ); + } + public void registerMappedSuperclassType( MappedSuperclass mappedSuperclass, MappedSuperclassDomainType mappedSuperclassType) { @@ -428,15 +441,8 @@ public class MetadataContext { final Class componentClass = identifier.getComponentClass(); final JavaType javaTypeDescriptor = registry.resolveManagedTypeDescriptor( componentClass ); - final EmbeddableRepresentationStrategy representationStrategy = getTypeConfiguration() - .getMetadataBuildingContext() - .getBuildingOptions() - .getManagedTypeRepresentationResolver() - .resolveStrategy( idClass, getRuntimeModelCreationContext() ); - final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl<>( javaTypeDescriptor, - representationStrategy, false, getJpaMetamodel() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java index 658dfe8233..ffed4a3862 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java @@ -92,15 +92,10 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp MappingModelCreationProcess creationProcess) { final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext(); - final EmbeddableRepresentationStrategy representationStrategy = creationContext.getBootstrapContext() - .getRepresentationStrategySelector() - .resolveStrategy( bootDescriptor, creationContext ); - final EmbeddableMappingType mappingType = new EmbeddableMappingType( bootDescriptor, - representationStrategy, embeddedPartBuilder, - creationContext.getSessionFactory() + creationContext ); if ( compositeType instanceof CompositeTypeImplementor ) { @@ -157,12 +152,15 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp private EmbeddableMappingType( Component bootDescriptor, - EmbeddableRepresentationStrategy representationStrategy, Function embeddedPartBuilder, - SessionFactoryImplementor sessionFactory) { + RuntimeModelCreationContext creationContext) { + this.representationStrategy = creationContext + .getBootstrapContext() + .getRepresentationStrategySelector() + .resolveStrategy( bootDescriptor, () -> this, creationContext ); + this.embeddableJtd = representationStrategy.getMappedJavaTypeDescriptor(); - this.representationStrategy = representationStrategy; - this.sessionFactory = sessionFactory; + this.sessionFactory = creationContext.getSessionFactory(); this.valueMapping = embeddedPartBuilder.apply( this ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/EmbeddableDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/EmbeddableDomainType.java index db606bb47c..f7e4cb3508 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/EmbeddableDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/EmbeddableDomainType.java @@ -8,8 +8,6 @@ package org.hibernate.metamodel.model.domain; import jakarta.persistence.metamodel.EmbeddableType; -import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy; - /** * Hibernate extension to the JPA {@link EmbeddableType} contract. * @@ -19,5 +17,4 @@ import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy; * @author Steve Ebersole */ public interface EmbeddableDomainType extends ManagedDomainType, EmbeddableType, AllowableParameterType { - ManagedTypeRepresentationStrategy getRepresentationStrategy(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java index 4096991dc9..f35b5657cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java @@ -7,16 +7,12 @@ package org.hibernate.metamodel.model.domain.internal; import java.io.Serializable; -import java.util.Map; -import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.graph.internal.SubGraphImpl; import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.metamodel.model.domain.AbstractManagedType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; -import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; -import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy; import org.hibernate.type.descriptor.java.JavaType; /** @@ -31,40 +27,15 @@ public class EmbeddableTypeImpl implements EmbeddableDomainType, Serializable { private final boolean isDynamic; - private final EmbeddableRepresentationStrategy representationStrategy; public EmbeddableTypeImpl( JavaType javaTypeDescriptor, - EmbeddableRepresentationStrategy representationStrategy, boolean isDynamic, JpaMetamodel domainMetamodel) { super( javaTypeDescriptor.getJavaType().getTypeName(), javaTypeDescriptor, null, domainMetamodel ); - this.representationStrategy = representationStrategy; this.isDynamic = isDynamic; } - public EmbeddableTypeImpl( - String name, - JpaMetamodel domainMetamodel) { - //noinspection unchecked - super( - name, - (JavaType) domainMetamodel.getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( Map.class ), - null, - domainMetamodel - ); - - // todo (6.0) : need ManagedTypeRepresentationStrategy impls - throw new NotYetImplementedFor6Exception( getClass() ); - } - - @Override - public ManagedTypeRepresentationStrategy getRepresentationStrategy() { - return representationStrategy; - } - @Override public PersistenceType getPersistenceType() { return PersistenceType.EMBEDDABLE; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index 8d1723622b..3efc8c02f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -43,6 +43,7 @@ import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; import org.hibernate.metamodel.internal.MetadataContext; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; @@ -488,6 +489,7 @@ public class JpaMetamodelImpl implements JpaMetamodel, Serializable { public void processJpa( MetadataImplementor bootMetamodel, + MappingMetamodel mappingMetamodel, Map entityProxyInterfaceMap, JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting, Collection namedEntityGraphDefinitions, @@ -495,62 +497,63 @@ public class JpaMetamodelImpl implements JpaMetamodel, Serializable { bootMetamodel.getImports().forEach( ( k, v ) -> this.nameToImportMap.put( k, new ImportInfo<>( v, null ) ) ); this.entityProxyInterfaceMap.putAll( entityProxyInterfaceMap ); - // todo (6.0) : I believe there should be a distinction here between building the JPA metamodel and pushing that metamodel to the `X_` model - // - JpaStaticMetaModelPopulationSetting is meant to control the latter part - populating the `X_` model - if ( jpaStaticMetaModelPopulationSetting != JpaStaticMetaModelPopulationSetting.DISABLED ) { - MetadataContext context = new MetadataContext( - this, - runtimeModelCreationContext, - bootMetamodel.getMappedSuperclassMappingsCopy(), - jpaStaticMetaModelPopulationSetting - ); + final MetadataContext context = new MetadataContext( + this, + mappingMetamodel, + bootMetamodel, + jpaStaticMetaModelPopulationSetting, + runtimeModelCreationContext + ); - for ( PersistentClass entityBinding : bootMetamodel.getEntityBindings() ) { - locateOrBuildEntityType( entityBinding, context, typeConfiguration ); - } - handleUnusedMappedSuperclasses( context, typeConfiguration ); - context.wrapUp(); + for ( PersistentClass entityBinding : bootMetamodel.getEntityBindings() ) { + locateOrBuildEntityType( entityBinding, context, typeConfiguration ); + } + handleUnusedMappedSuperclasses( context, typeConfiguration ); - this.jpaEntityTypeMap.putAll( context.getEntityTypesByEntityName() ); - this.jpaMappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() ); + context.wrapUp(); - for ( EmbeddableDomainType embeddable : context.getEmbeddableTypeSet() ) { - this.jpaEmbeddableDescriptorMap.put( embeddable.getJavaType(), embeddable ); - } - Stream.concat( - context.getEntityTypesByEntityName().values().stream(), - Stream.concat( - context.getMappedSuperclassTypeMap().values().stream(), - context.getEmbeddableTypeSet().stream() - ) - ).forEach( managedDomainType -> { - managedDomainType.visitAttributes( persistentAttribute -> { - if ( persistentAttribute.getJavaType() != null && persistentAttribute.getJavaType().isEnum() ) { - @SuppressWarnings("unchecked") - Class> enumClass = (Class>) persistentAttribute.getJavaType(); - Enum[] enumConstants = enumClass.getEnumConstants(); - for ( Enum enumConstant : enumConstants ) { - String qualifiedEnumLiteral = enumConstant.getDeclaringClass() - .getSimpleName() + "." + enumConstant.name(); + this.jpaEntityTypeMap.putAll( context.getEntityTypesByEntityName() ); + this.jpaMappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() ); - this.allowedEnumLiteralTexts.computeIfAbsent( - enumConstant.name(), - k -> new ConcurrentHashMap<>() - ).put( enumClass, enumConstant ); - this.allowedEnumLiteralTexts.computeIfAbsent( - qualifiedEnumLiteral, - k -> new ConcurrentHashMap<>() - ).put( enumClass, enumConstant ); - } - } - } ); - } ); + for ( EmbeddableDomainType embeddable : context.getEmbeddableTypeSet() ) { + this.jpaEmbeddableDescriptorMap.put( embeddable.getJavaType(), embeddable ); } + domainTypeStream( context ).forEach( (managedDomainType) -> managedDomainType.visitAttributes( persistentAttribute -> { + if ( persistentAttribute.getJavaType() != null && persistentAttribute.getJavaType().isEnum() ) { + @SuppressWarnings("unchecked") + Class> enumClass = (Class>) persistentAttribute.getJavaType(); + Enum[] enumConstants = enumClass.getEnumConstants(); + for ( Enum enumConstant : enumConstants ) { + String qualifiedEnumLiteral = enumConstant.getDeclaringClass() + .getSimpleName() + "." + enumConstant.name(); + + this.allowedEnumLiteralTexts.computeIfAbsent( + enumConstant.name(), + k -> new ConcurrentHashMap<>() + ).put( enumClass, enumConstant ); + this.allowedEnumLiteralTexts.computeIfAbsent( + qualifiedEnumLiteral, + k -> new ConcurrentHashMap<>() + ).put( enumClass, enumConstant ); + } + } + } ) ); + applyNamedEntityGraphs( namedEntityGraphDefinitions ); } + private static Stream> domainTypeStream(MetadataContext context) { + return Stream.concat( + context.getEntityTypesByEntityName().values().stream(), + Stream.concat( + context.getMappedSuperclassTypeMap().values().stream(), + context.getEmbeddableTypeSet().stream() + ) + ); + } + private EntityDomainType locateOrBuildEntityType( PersistentClass persistentClass, MetadataContext context, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java index 31ab4798d3..dfb2a9176e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java @@ -233,6 +233,7 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen ( (JpaMetamodelImpl) this.jpaMetamodel ).processJpa( bootModel, + this, entityProxyInterfaceMap, jpaStaticMetaModelPopulationSetting, bootModel.getNamedEntityGraphs().values(), diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ManagedTypeRepresentationResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ManagedTypeRepresentationResolver.java index 8fc6ddb176..18d2794a4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ManagedTypeRepresentationResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ManagedTypeRepresentationResolver.java @@ -6,9 +6,12 @@ */ package org.hibernate.metamodel.spi; +import java.util.function.Supplier; + import org.hibernate.Incubating; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.persister.entity.EntityPersister; /** @@ -35,5 +38,6 @@ public interface ManagedTypeRepresentationResolver { */ EmbeddableRepresentationStrategy resolveStrategy( Component bootDescriptor, + Supplier runtimeDescriptor, RuntimeModelCreationContext creationContext); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java index 9fda8eba0b..b7ec8aeb45 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java @@ -151,7 +151,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA compositeInstance = embeddableTypeDescriptor .getRepresentationStrategy() .getInstantiator() - .instantiate( VALUE_ACCESS, rowProcessingState.getSession().getFactory() ); + .instantiate( null, rowProcessingState.getSession().getFactory() ); } EmbeddableLoadingLogger.INSTANCE.debugf( @@ -160,10 +160,6 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA ); } - private static Supplier VALUE_ACCESS = () -> { - throw new NotYetImplementedFor6Exception( "Constructor value injection for embeddables not yet implemented" ); - }; - @Override public void initializeInstance(RowProcessingState rowProcessingState) { @@ -232,7 +228,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA Object target = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor() .getRepresentationStrategy() .getInstantiator() - .instantiate( VALUE_ACCESS, rowProcessingState.getSession().getFactory() ); + .instantiate( null, rowProcessingState.getSession().getFactory() ); embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues( target, resolvedValues diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/intg/sqm/HqlTranslationNoFactoryTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/intg/sqm/HqlTranslationNoFactoryTests.java deleted file mode 100644 index 6afea46b4e..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/intg/sqm/HqlTranslationNoFactoryTests.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.orm.test.intg.sqm; - -import java.util.Collections; -import java.util.Optional; - -import org.hibernate.boot.spi.BootstrapContext; -import org.hibernate.boot.spi.MetadataImplementor; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.orm.test.jpa.JpaComplianceStub; -import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; -import org.hibernate.metamodel.model.domain.JpaMetamodel; -import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl; -import org.hibernate.metamodel.MappingMetamodel; -import org.hibernate.metamodel.spi.RuntimeModelCreationContext; -import org.hibernate.query.criteria.ValueHandlingMode; -import org.hibernate.query.hql.HqlTranslator; -import org.hibernate.query.hql.internal.StandardHqlTranslator; -import org.hibernate.query.hql.spi.SqmCreationOptions; -import org.hibernate.query.internal.NamedObjectRepositoryImpl; -import org.hibernate.query.named.NamedObjectRepository; -import org.hibernate.query.spi.QueryEngine; -import org.hibernate.query.sqm.spi.SqmCreationContext; -import org.hibernate.query.sqm.tree.SqmStatement; -import org.hibernate.type.spi.TypeConfiguration; - -import org.hibernate.testing.orm.domain.StandardDomainModel; -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.DomainModelScope; -import org.hibernate.testing.orm.junit.FailureExpected; -import org.hibernate.testing.orm.junit.ServiceRegistry; -import org.hibernate.testing.orm.junit.ServiceRegistryScope; -import org.junit.jupiter.api.Test; - -/** - * Tests making sure that HQL queries can fully be translated without a SessionFactory. - * - * todo (6.0) : have a way to directly load these translations into the {@link NamedObjectRepository} - * directly. For example Quarkus could store its build-time translations and directly here during boot-strap of the SF - * - * @author Steve Ebersole - */ -@ServiceRegistry -@DomainModel( standardModels = StandardDomainModel.RETAIL ) -public class HqlTranslationNoFactoryTests { - @Test - @FailureExpected( reason = "Building the JpaDomain") - public void testHqlTranslationNoSessionFactory(DomainModelScope modelScope, ServiceRegistryScope registryScope) { - final String hql = "select a from SalesAssociate a"; - - final HqlTranslator hqlTranslator = buildHqlTranslator( modelScope, registryScope ); - final SqmStatement sqmStatement = hqlTranslator.translate( hql ); - assert sqmStatement != null; - } - - private HqlTranslator buildHqlTranslator(DomainModelScope modelScope, ServiceRegistryScope registryScope) { - final MetadataImplementor bootModel = modelScope.getDomainModel(); - final TypeConfiguration typeConfiguration = bootModel.getTypeConfiguration(); - - final JpaMetamodelImpl jpaMetamodel = new JpaMetamodelImpl( typeConfiguration, new JpaComplianceStub() ); - - // todo (6.0) (quarkus) : we should limit the type of the last argument here from `RuntimeModelCreationContext` - // which assumes access to SessionFactory - jpaMetamodel.processJpa( - bootModel, - Collections.emptyMap(), - JpaStaticMetaModelPopulationSetting.ENABLED, - Collections.emptyList(), - new RuntimeModelCreationContext() { - @Override - public SessionFactoryImplementor getSessionFactory() { - throw new UnsupportedOperationException( "SessionFactory not available" ); - } - - @Override - public BootstrapContext getBootstrapContext() { - return typeConfiguration.getMetadataBuildingContext().getBootstrapContext(); - } - - @Override - public MetadataImplementor getBootModel() { - return modelScope.getDomainModel(); - } - - @Override - public MappingMetamodel getDomainModel() { - throw new UnsupportedOperationException( "DomainMetamodel not available" ); - } - } - ); - - Optional queryEngineAccess = Optional.empty(); - - // todo (6.0) (quarkus) : this circularity is problematic as well - // between `SqmCreationContext#getQueryEngine` and the `SqmCreationContext` passed to `#QueryEngine` - final SqmCreationContext sqmCreationContext = new SqmCreationContext() { - @Override - public JpaMetamodel getJpaMetamodel() { - return jpaMetamodel; - } - - @Override - public QueryEngine getQueryEngine() { - return queryEngineAccess.orElseThrow( () -> new RuntimeException( "Unexpected access to `SqmCreationContext#getQueryEngine`" ) ); - } - }; - - // we don't want strict JPA query compliance - final SqmCreationOptions sqmCreationOptions = () -> false; - - final QueryEngine queryEngine = new QueryEngine( - null, - null, - jpaMetamodel, - ValueHandlingMode.BIND, - ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( registryScope.getRegistry() ), - // we don't want strict JPA query compliance - false, - new NamedObjectRepositoryImpl( Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap() ), - // NativeQueryInterpreter - null, - // this is exclusively to build the SqmFunctionRegistry, maybe Quarkus should just build it directly and pass - registryScope.getRegistry().getService( JdbcServices.class ).getDialect(), - registryScope.getRegistry() - ); - - return new StandardHqlTranslator( - new SqmCreationContext() { - @Override - public JpaMetamodel getJpaMetamodel() { - return jpaMetamodel; - } - - @Override - public QueryEngine getQueryEngine() { - return queryEngine; - } - }, - sqmCreationOptions - ); - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/strategy/FromAttributeFactoryTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/strategy/FromAttributeFactoryTests.java new file mode 100644 index 0000000000..32412ad377 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/strategy/FromAttributeFactoryTests.java @@ -0,0 +1,25 @@ +/* + * 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.orm.test.mapping.embeddable.strategy; + +import org.hibernate.testing.orm.domain.gambit.EntityOfComposites; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +/** + * @author Steve Ebersole + */ +@DomainModel( annotatedClasses = EntityOfComposites.class ) +@SessionFactory +public class FromAttributeFactoryTests { + @Test + public void simpleTest(SessionFactoryScope scope) { + scope.getSessionFactory().getRuntimeMetamodels(); + } +}