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:
parent
546a635be9
commit
0322d8fa84
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue