Introduce `VirtualIdEmbeddable` and `IdClassEmbeddable`

EmbeddableInstantiator

Still need to
  - integrate EmbeddableInstantiator work
  - integrate embedded forms.  `VirtualIdEmbeddable` does not really need it as it can use the id-mapping itself as the embedded form.  But `IdClassEmbedded` should really be integrated
  - integrate `VirtualKeyEmbeddable` and `VirtualKeyEmbedded` for use as inverse composite fks
  - share `#finishInit` handling for `EmbeddableMappingType`, `VirtualIdEmbeddable` and `IdClassEmbeddable`
This commit is contained in:
Steve Ebersole 2021-11-21 09:21:59 -06:00
parent 546a635be9
commit 0322d8fa84
12 changed files with 98 additions and 105 deletions

View File

@ -8,64 +8,45 @@ package org.hibernate.bytecode.spi;
/** /**
* Represents reflection optimization for a particular class. * Represents reflection optimization for a particular class.
*
* @author Steve Ebersole
*/ */
public interface ReflectionOptimizer { public interface ReflectionOptimizer {
/** /**
* Retrieve the optimizer for calling an entity's constructor via reflection. * Retrieve the optimizer for calling an entity's constructor via reflection.
*
* @return The optimizer for instantiation
*/ */
public InstantiationOptimizer getInstantiationOptimizer(); InstantiationOptimizer getInstantiationOptimizer();
/** /**
* Retrieve the optimizer for accessing the entity's persistent state. * Retrieve the optimizer for accessing the entity's persistent state.
*
* @return The optimizer for persistent state access
*/ */
public AccessOptimizer getAccessOptimizer(); AccessOptimizer getAccessOptimizer();
/** /**
* Represents optimized entity instantiation. * Represents optimized entity instantiation.
*/ */
public static interface InstantiationOptimizer { interface InstantiationOptimizer {
/** /**
* Perform instantiation of an instance of the underlying class. * Perform instantiation of an instance of the underlying class.
*
* @return The new instance.
*/ */
public Object newInstance(); Object newInstance();
} }
/** /**
* Represents optimized entity property access. * Represents optimized entity property access.
*
* @author Steve Ebersole
*/ */
public interface AccessOptimizer { interface AccessOptimizer {
/** /**
* Get the name of all properties. * Get the name of all properties.
*
* @return The name of all properties.
*/ */
public String[] getPropertyNames(); String[] getPropertyNames();
/** /**
* Get the value of all properties from the given entity * Get the value of all properties from the given entity
*
* @param object The entity from which to extract values.
*
* @return The values.
*/ */
public Object[] getPropertyValues(Object object); Object[] getPropertyValues(Object object);
/** /**
* Set all property values into an entity instance. * Set all property values into an entity instance.
*
* @param object The entity instance
* @param values The values to inject
*/ */
public void setPropertyValues(Object object, Object[] values); void setPropertyValues(Object object, Object[] values);
} }
} }

View File

@ -7,12 +7,15 @@
package org.hibernate.loader; package org.hibernate.loader;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.NavigablePath;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class PropertyPath { public class PropertyPath {
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper"; public static final String IDENTIFIER_MAPPER_PROPERTY = NavigablePath.IDENTIFIER_MAPPER_PROPERTY;
private final PropertyPath parent; private final PropertyPath parent;
private final String property; private final String property;
private final String fullPath; private final String fullPath;

View File

@ -9,6 +9,7 @@ package org.hibernate.metamodel.internal;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -17,21 +18,25 @@ import static org.hibernate.bytecode.spi.ReflectionOptimizer.InstantiationOptimi
/** /**
* Support for instantiating embeddables as POJO representation * Support for instantiating embeddables as POJO representation
* using bytecode optimizer * using bytecode optimizer
*
* @author Steve Ebersole
*/ */
public class EmbeddableInstantiatorPojoOptimized extends AbstractPojoInstantiator implements EmbeddableInstantiator { public class EmbeddableInstantiatorPojoOptimized extends AbstractPojoInstantiator implements EmbeddableInstantiator {
private final Supplier<EmbeddableMappingType> embeddableMappingAccess;
private final InstantiationOptimizer instantiationOptimizer; private final InstantiationOptimizer instantiationOptimizer;
public EmbeddableInstantiatorPojoOptimized( public EmbeddableInstantiatorPojoOptimized(
JavaType<?> javaTypeDescriptor, JavaType<?> javaTypeDescriptor,
Supplier<EmbeddableMappingType> embeddableMappingAccess,
InstantiationOptimizer instantiationOptimizer) { InstantiationOptimizer instantiationOptimizer) {
super( javaTypeDescriptor.getJavaTypeClass() ); super( javaTypeDescriptor.getJavaTypeClass() );
this.embeddableMappingAccess = embeddableMappingAccess;
this.instantiationOptimizer = instantiationOptimizer; this.instantiationOptimizer = instantiationOptimizer;
} }
@Override @Override
public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) { public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) {
return instantiationOptimizer.newInstance(); final Object embeddable = instantiationOptimizer.newInstance();
final EmbeddableMappingType embeddableMapping = embeddableMappingAccess.get();
embeddableMapping.setPropertyValues( embeddable, valuesAccess.get() );
return embeddable;
} }
} }

View File

@ -10,7 +10,6 @@ import java.lang.reflect.Constructor;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.InstantiationException; import org.hibernate.InstantiationException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.PropertyNotFoundException; import org.hibernate.PropertyNotFoundException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -22,18 +21,15 @@ import org.hibernate.type.descriptor.java.JavaType;
/** /**
* Support for instantiating embeddables as POJO representation * Support for instantiating embeddables as POJO representation
*
* @author Steve Ebersole
*/ */
public class EmbeddableInstantiatorPojoStandard extends AbstractPojoInstantiator implements EmbeddableInstantiator { public class EmbeddableInstantiatorPojoStandard extends AbstractPojoInstantiator implements EmbeddableInstantiator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiatorImpl.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiatorImpl.class );
private final Supplier<EmbeddableMappingType> embeddableMappingAccess; private final Supplier<EmbeddableMappingType> embeddableMappingAccess;
private final boolean constructorInjection = false;
private final Constructor<?> constructor; private final Constructor<?> constructor;
public EmbeddableInstantiatorPojoStandard( public EmbeddableInstantiatorPojoStandard(JavaType<?> javaTypeDescriptor, Supplier<EmbeddableMappingType> embeddableMappingAccess) {
Supplier<EmbeddableMappingType> embeddableMappingAccess,
JavaType<?> javaTypeDescriptor) {
super( javaTypeDescriptor.getJavaTypeClass() ); super( javaTypeDescriptor.getJavaTypeClass() );
this.embeddableMappingAccess = embeddableMappingAccess; this.embeddableMappingAccess = embeddableMappingAccess;
@ -54,29 +50,29 @@ public class EmbeddableInstantiatorPojoStandard extends AbstractPojoInstantiator
@Override @Override
public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) { public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) {
if ( isAbstract() ) { if ( isAbstract() ) {
throw new InstantiationException( "Cannot instantiate abstract class or interface: ", getMappedPojoClass() ); throw new InstantiationException(
"Cannot instantiate abstract class or interface: ", getMappedPojoClass()
);
} }
if ( constructor == null ) { if ( constructor == null ) {
throw new InstantiationException( "No default constructor for embeddable: ", getMappedPojoClass() ); throw new InstantiationException( "Unable to locate constructor for embeddable", getMappedPojoClass() );
}
if ( valuesAccess != null ) {
if ( constructor.getParameterTypes().length > 0 ) {
// constructor injection
throw new NotYetImplementedFor6Exception( "Constructor injection for embeddables not yet implemented" );
}
} }
try { try {
if ( constructorInjection ) {
return constructor.newInstance( valuesAccess.get() );
}
final Object instance = constructor.newInstance(); final Object instance = constructor.newInstance();
if ( valuesAccess != null ) { if ( valuesAccess != null ) {
embeddableMappingAccess.get().setPropertyValues( instance, valuesAccess.get() ); embeddableMappingAccess.get().setPropertyValues( instance, valuesAccess.get() );
} }
return instance; return instance;
} }
catch ( Exception e ) { catch ( Exception e ) {
throw new InstantiationException( "Could not instantiate embeddable: ", getMappedPojoClass(), e ); throw new InstantiationException( "Could not instantiate entity: ", getMappedPojoClass(), e );
} }
} }
} }

View File

@ -75,14 +75,12 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr
final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer(); final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer();
return new EmbeddableInstantiatorPojoOptimized( return new EmbeddableInstantiatorPojoOptimized(
getEmbeddableJavaTypeDescriptor(), getEmbeddableJavaTypeDescriptor(),
runtimeDescriptorAccess,
instantiationOptimizer instantiationOptimizer
); );
} }
return new EmbeddableInstantiatorPojoStandard( return new EmbeddableInstantiatorPojoStandard( getEmbeddableJavaTypeDescriptor(), runtimeDescriptorAccess );
runtimeDescriptorAccess,
getEmbeddableJavaTypeDescriptor()
);
} }
@Override @Override

View File

@ -43,6 +43,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelCreationLogger; import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping; import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
@ -50,7 +51,6 @@ import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.SingularAttributeMapping; import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata; import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess; import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -17,7 +17,7 @@ import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
/** /**
* @author Steve Ebersole * EmbeddableRepresentationStrategy for an IdClass mapping
*/ */
public class IdClassRepresentationStrategy implements EmbeddableRepresentationStrategy { public class IdClassRepresentationStrategy implements EmbeddableRepresentationStrategy {
private final JavaType<?> idClassType; private final JavaType<?> idClassType;
@ -25,7 +25,7 @@ public class IdClassRepresentationStrategy implements EmbeddableRepresentationSt
public IdClassRepresentationStrategy(IdClassEmbeddable idClassEmbeddable) { public IdClassRepresentationStrategy(IdClassEmbeddable idClassEmbeddable) {
this.idClassType = idClassEmbeddable.getMappedJavaTypeDescriptor(); this.idClassType = idClassEmbeddable.getMappedJavaTypeDescriptor();
this.instantiator = new EmbeddableInstantiatorPojoStandard( () -> idClassEmbeddable, idClassType ); this.instantiator = new EmbeddableInstantiatorPojoStandard( idClassType, () -> idClassEmbeddable );
} }
@Override @Override

View File

@ -18,9 +18,9 @@ import org.hibernate.mapping.Component;
import org.hibernate.mapping.RootClass; import org.hibernate.mapping.RootClass;
import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping; import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping; import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;

View File

@ -10,6 +10,7 @@ import java.util.Objects;
import org.hibernate.query.DotIdentifierSequence; import org.hibernate.query.DotIdentifierSequence;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.NavigablePath;
/** /**
* Poorly named. * Poorly named.
@ -21,7 +22,7 @@ import org.hibernate.internal.util.StringHelper;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NavigableRole implements DotIdentifierSequence { public class NavigableRole implements DotIdentifierSequence {
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper"; public static final String IDENTIFIER_MAPPER_PROPERTY = NavigablePath.IDENTIFIER_MAPPER_PROPERTY;
private final NavigableRole parent; private final NavigableRole parent;
private final String localName; private final String localName;

View File

@ -6,18 +6,22 @@
*/ */
package org.hibernate.metamodel.spi; package org.hibernate.metamodel.spi;
import java.util.function.IntFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
/** /**
* Contract for instantiating embeddable values * Contract for instantiating embeddable values
*
* @author Steve Ebersole
*/ */
public interface EmbeddableInstantiator extends Instantiator { public interface EmbeddableInstantiator extends Instantiator {
/** /**
* Create an instance of the embeddable * Create an instance of the embeddable
*/ */
Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory); Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory);
// default Object instantiate(IntFunction<Object> valueAccess, SessionFactoryImplementor sessionFactory) {
// throw new NotYetImplementedFor6Exception( getClass() );
// }
} }

View File

@ -39,5 +39,7 @@ public abstract class AbstractFetchParentAccess implements FetchParentAccess {
for ( Consumer<Object> listener : listeners ) { for ( Consumer<Object> listener : listeners ) {
listener.accept( parentInstance ); listener.accept( parentInstance );
} }
listeners.clear();
} }
} }

View File

@ -6,19 +6,16 @@
*/ */
package org.hibernate.sql.results.graph.embeddable; package org.hibernate.sql.results.graph.embeddable;
import java.util.IdentityHashMap; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
@ -37,15 +34,20 @@ import org.hibernate.sql.results.internal.NullValueAssembler;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.spi.EntityJavaTypeDescriptor; import org.hibernate.type.descriptor.java.spi.EntityJavaTypeDescriptor;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentAccess implements EmbeddableInitializer { public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentAccess implements EmbeddableInitializer {
public static final Object NULL_MARKER = new Object();
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
private final EmbeddableValuedModelPart embeddedModelPartDescriptor; private final EmbeddableValuedModelPart embedded;
private final EmbeddableRepresentationStrategy representationStrategy;
private FetchParentAccess fetchParentAccess; private FetchParentAccess fetchParentAccess;
private final Map<StateArrayContributorMapping, DomainResultAssembler> assemblerMap; private final List<DomainResultAssembler<?>> assemblers;
// per-row state // per-row state
private final Object[] resolvedValues; private final Object[] resolvedValues;
@ -59,15 +61,25 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
FetchParentAccess fetchParentAccess, FetchParentAccess fetchParentAccess,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
this.navigablePath = resultDescriptor.getNavigablePath(); this.navigablePath = resultDescriptor.getNavigablePath();
this.embeddedModelPartDescriptor = resultDescriptor.getReferencedMappingContainer(); this.embedded = resultDescriptor.getReferencedMappingContainer();
this.fetchParentAccess = fetchParentAccess; this.fetchParentAccess = fetchParentAccess;
final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor(); final EmbeddableMappingType embeddableTypeDescriptor = embedded.getEmbeddableTypeDescriptor();
if ( embedded instanceof CompositeIdentifierMapping ) {
representationStrategy = ( (CompositeIdentifierMapping) embedded )
.getMappedIdEmbeddableTypeDescriptor()
.getRepresentationStrategy();
}
else {
representationStrategy = embeddableTypeDescriptor.getRepresentationStrategy();
}
final int numOfAttrs = embeddableTypeDescriptor.getNumberOfAttributeMappings(); final int numOfAttrs = embeddableTypeDescriptor.getNumberOfAttributeMappings();
this.resolvedValues = new Object[ numOfAttrs ]; this.resolvedValues = new Object[ numOfAttrs ];
this.assemblerMap = new IdentityHashMap<>( numOfAttrs ); this.assemblers = arrayList( numOfAttrs );
embeddedModelPartDescriptor.visitFetchables( embeddableTypeDescriptor.visitFetchables(
stateArrayContributor -> { stateArrayContributor -> {
final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor ); final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor );
@ -75,7 +87,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
? new NullValueAssembler<>( stateArrayContributor.getJavaTypeDescriptor() ) ? new NullValueAssembler<>( stateArrayContributor.getJavaTypeDescriptor() )
: fetch.createAssembler( this, creationState ); : fetch.createAssembler( this, creationState );
assemblerMap.put( (StateArrayContributorMapping) stateArrayContributor, stateAssembler ); assemblers.add( stateAssembler );
}, },
null null
); );
@ -89,7 +101,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override @Override
public EmbeddableValuedModelPart getInitializedPart() { public EmbeddableValuedModelPart getInitializedPart() {
return embeddedModelPartDescriptor; return embedded;
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -103,7 +115,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override @Override
public Object getCompositeInstance() { public Object getCompositeInstance() {
return compositeInstance; return compositeInstance == NULL_MARKER ? null : compositeInstance;
} }
@Override @Override
@ -111,9 +123,10 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
if ( compositeInstance != null ) { if ( compositeInstance != null ) {
return; return;
} }
final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess();
final PropertyAccess parentInjectionPropertyAccess = embedded.getParentInjectionAttributePropertyAccess();
final FetchParentAccess fetchParentAccess = getFetchParentAccess(); final FetchParentAccess fetchParentAccess = getFetchParentAccess();
if ( parentInjectionPropertyAccess != null && fetchParentAccess != null ) { if ( parentInjectionPropertyAccess != null && fetchParentAccess != null ) {
fetchParentAccess.findFirstEntityDescriptorAccess().registerResolutionListener( fetchParentAccess.findFirstEntityDescriptorAccess().registerResolutionListener(
// todo (6.0) : this is the legacy behavior // todo (6.0) : this is the legacy behavior
@ -142,26 +155,20 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
// Special handling for non-aggregated attributes which use the actual entity instance as container, // Special handling for non-aggregated attributes which use the actual entity instance as container,
// which we access through the fetch parent access. // which we access through the fetch parent access.
// If this model part is an identifier, we must construct the instance as this is called during resolveKey // If this model part is an identifier, we must construct the instance as this is called during resolveKey
final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor(); final EmbeddableMappingType embeddableTypeDescriptor = embedded.getEmbeddableTypeDescriptor();
final EmbeddableRepresentationStrategy representationStrategy;
if ( embeddedModelPartDescriptor instanceof CompositeIdentifierMapping ) {
representationStrategy = ( (CompositeIdentifierMapping) embeddedModelPartDescriptor ).getMappedIdEmbeddableTypeDescriptor()
.getRepresentationStrategy();
}
else {
representationStrategy = embeddableTypeDescriptor.getRepresentationStrategy();
}
if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor().getJavaTypeClass() if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor().getJavaTypeClass()
.isAssignableFrom( fetchParentAccess.getInitializedPart().getJavaTypeDescriptor().getJavaTypeClass() ) .isAssignableFrom( fetchParentAccess.getInitializedPart().getJavaTypeDescriptor().getJavaTypeClass() )
&& embeddableTypeDescriptor.getMappedJavaTypeDescriptor() instanceof EntityJavaTypeDescriptor<?> && embeddableTypeDescriptor.getMappedJavaTypeDescriptor() instanceof EntityJavaTypeDescriptor<?>
&& !( embeddedModelPartDescriptor instanceof CompositeIdentifierMapping ) && !( embedded instanceof CompositeIdentifierMapping )
&& !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( embeddedModelPartDescriptor.getFetchableName() ) ) { && !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( embedded.getFetchableName() ) ) {
fetchParentAccess.resolveInstance( rowProcessingState ); fetchParentAccess.resolveInstance( rowProcessingState );
compositeInstance = fetchParentAccess.getInitializedInstance(); compositeInstance = fetchParentAccess.getInitializedInstance();
} }
if ( compositeInstance == null ) { if ( compositeInstance == null ) {
compositeInstance = representationStrategy.getInstantiator() compositeInstance = representationStrategy
.getInstantiator()
.instantiate( null, rowProcessingState.getSession().getFactory() ); .instantiate( null, rowProcessingState.getSession().getFactory() );
} }
@ -173,10 +180,9 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override @Override
public void initializeInstance(RowProcessingState rowProcessingState) { public void initializeInstance(RowProcessingState rowProcessingState) {
final PropertyAccess parentInjectionPropertyAccess = embedded.getParentInjectionAttributePropertyAccess();
final Initializer initializer = rowProcessingState.resolveInitializer( navigablePath.getParent() );
final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess();
Initializer initializer = rowProcessingState.resolveInitializer( navigablePath.getParent() );
if ( parentInjectionPropertyAccess != null ) { if ( parentInjectionPropertyAccess != null ) {
final Object owner; final Object owner;
if ( initializer instanceof CollectionInitializer ) { if ( initializer instanceof CollectionInitializer ) {
@ -207,16 +213,14 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
); );
boolean areAllValuesNull = true; boolean areAllValuesNull = true;
final Set<Map.Entry<StateArrayContributorMapping, DomainResultAssembler>> entries = assemblerMap.entrySet(); for ( int i = 0; i < assemblers.size(); i++ ) {
final int size = entries.size(); final DomainResultAssembler<?> assembler = assemblers.get( i );
for ( Map.Entry<StateArrayContributorMapping, DomainResultAssembler> entry : entries ) {
final DomainResultAssembler<?> assembler = entry.getValue();
final Object contributorValue = assembler.assemble( final Object contributorValue = assembler.assemble(
rowProcessingState, rowProcessingState,
rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
); );
resolvedValues[entry.getKey().getStateArrayPosition()] = contributorValue; resolvedValues[i] = contributorValue;
if ( contributorValue != null ) { if ( contributorValue != null ) {
areAllValuesNull = false; areAllValuesNull = false;
} }
@ -234,8 +238,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
); );
} }
else { else {
Object target = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor() Object target = representationStrategy
.getRepresentationStrategy()
.getInstantiator() .getInstantiator()
.instantiate( null, rowProcessingState.getSession().getFactory() ); .instantiate( null, rowProcessingState.getSession().getFactory() );
setPropertyValuesOnTarget( target, rowProcessingState.getSession() ); setPropertyValuesOnTarget( target, rowProcessingState.getSession() );
@ -258,23 +261,23 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
private void setPropertyValuesOnTarget(Object compositeInstance, SharedSessionContractImplementor session) { private void setPropertyValuesOnTarget(Object compositeInstance, SharedSessionContractImplementor session) {
final EmbeddableMappingType embeddableTypeDescriptor; final EmbeddableMappingType embeddableTypeDescriptor;
if ( embeddedModelPartDescriptor instanceof CompositeIdentifierMapping ) { if ( embedded instanceof CompositeIdentifierMapping ) {
final CompositeIdentifierMapping compositeIdentifierMapping = (CompositeIdentifierMapping) this.embeddedModelPartDescriptor; final CompositeIdentifierMapping compositeIdentifierMapping = (CompositeIdentifierMapping) embedded;
embeddableTypeDescriptor = compositeIdentifierMapping.getMappedIdEmbeddableTypeDescriptor(); embeddableTypeDescriptor = compositeIdentifierMapping.getMappedIdEmbeddableTypeDescriptor();
if ( compositeIdentifierMapping.hasContainingClass() ) { if ( compositeIdentifierMapping.hasContainingClass() ) {
// For id-classes, we might have to transform from the virtual representation to the id-class representation // For id-classes, we might have to transform from the virtual representation to the id-class representation
// in case the virtual representation contains a to-one attribute, that is mapped by an embeddable in the id-class // in case the virtual representation contains a to-one attribute, that is mapped by an embeddable in the id-class
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().forEachAttributeMapping( embedded.getEmbeddableTypeDescriptor().forEachAttributeMapping(
(index, attributeMapping) -> { (index, attributeMapping) -> {
final AttributeMapping idClassAttribute = embeddableTypeDescriptor.getAttributeMappings().get( index ); final AttributeMapping idClassAttribute = embeddableTypeDescriptor.getAttributeMappings().get( index );
if ( attributeMapping instanceof ToOneAttributeMapping && !( idClassAttribute instanceof ToOneAttributeMapping ) ) { if ( attributeMapping instanceof ToOneAttributeMapping && !( idClassAttribute instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final Object associationKey = toOneAttributeMapping.getForeignKeyDescriptor() final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
.getAssociationKeyFromSide( final Object associationKey = fkDescriptor.getAssociationKeyFromSide(
resolvedValues[index], resolvedValues[index],
toOneAttributeMapping.getSideNature().inverse(), toOneAttributeMapping.getSideNature().inverse(),
session session
); );
resolvedValues[index] = associationKey; resolvedValues[index] = associationKey;
} }
} }
@ -282,7 +285,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
} }
} }
else { else {
embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor(); embeddableTypeDescriptor = embedded.getEmbeddableTypeDescriptor();
} }
embeddableTypeDescriptor.setPropertyValues( embeddableTypeDescriptor.setPropertyValues(
compositeInstance, compositeInstance,