Skip to content

Commit

Permalink
Introduce VirtualIdEmbeddable and IdClassEmbeddable + instantiators
Browse files Browse the repository at this point in the history
- Clean up Component Type, removing as many calls to its tuplizer as possible atm
- Clean up ManagedMappingType, EntityPersister, etc - mainly work around getting and setting value(s)

Still need to
  - 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`
  - ability to use the containing composite owner as the parent of a composite (legacy behavior is to always use the "first" entity
  - clean up ComponentType, esp wrt its use of ComponentTuplizer
  • Loading branch information
sebersole committed Dec 1, 2021
1 parent eb5afb0 commit b23c2f4
Show file tree
Hide file tree
Showing 45 changed files with 228 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public Collection getOrphans(Serializable snapshot, String entityName) throws Hi
public void initializeEmptyCollection(CollectionPersister persister) {
assert array == null;
array = Array.newInstance( persister.getElementClass(), 0 );
persister.getAttributeMapping().getPropertyAccess().getSetter().set( getOwner(), array, getSession().getFactory() );
persister.getAttributeMapping().getPropertyAccess().getSetter().set( getOwner(), array );
endRead();
}

Expand All @@ -149,7 +149,7 @@ public void injectLoadedState(PluralAttributeMapping attributeMapping, List load
Array.set( array, i, loadingState.get( i ) );
}
}
attributeMapping.getPropertyAccess().getSetter().set( getOwner(), array, getSession().getFactory() );
attributeMapping.getPropertyAccess().getSetter().set( getOwner(), array );
}

@SuppressWarnings("UnusedDeclaration")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ private void loadByDerivedIdentitySimplePkValue(
final Object parent = doLoad( event, parentPersister, parentEntityKey, options );

final Object dependent = dependentIdType.instantiate();
dependentIdType.getPartMappingType().setPropertyValues(
dependentIdType.getPartMappingType().setValues(
dependent,
new Object[] { parent }
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ public ValueGenerationPlan(
@Override
public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) {
final Object generatedValue = subGenerator.generate( session, incomingObject );
injector.set( injectionContext, generatedValue, session.getFactory() );
injector.set( injectionContext, generatedValue );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.Iterator;

import org.hibernate.AssertionFailure;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging;
import org.hibernate.mapping.Collection;
Expand All @@ -26,6 +28,8 @@
import org.hibernate.metamodel.AttributeClassification;
import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
Expand Down Expand Up @@ -608,23 +612,31 @@ else if ( member instanceof Method ) {


private static final MemberResolver virtualIdentifierMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType, metadataContext );
if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
throw new IllegalArgumentException( "expecting IdClass mapping" );
}

org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType();
if ( !(type instanceof EmbeddedComponentType) ) {
throw new IllegalArgumentException( "expecting IdClass mapping" );
}

final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
final String attributeName = attributeContext.getPropertyMapping().getName();
final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
final EmbeddableValuedModelPart embeddedPart = ( (CompositeTypeImplementor) componentType ).getMappingModelPart();
assert embeddedPart != null;
final EmbeddableMappingType embeddable = embeddedPart.getEmbeddableTypeDescriptor();
final AttributeMapping attributeMapping = embeddable.findAttributeMapping( attributeName );
if ( attributeMapping == null ) {
throw new PropertyNotFoundException(
"Unable to locate property named " + attributeName + " on " + embeddable.getJavaTypeDescriptor().getJavaTypeClass().getName()
);
}

final Getter getter = componentType.getComponentTuplizer()
.getGetter( componentType.getPropertyIndex( attributeName ) );

return PropertyAccessMapImpl.GetterImpl.class.isInstance( getter )
final Getter getter = attributeMapping.getPropertyAccess().getGetter();
return getter instanceof PropertyAccessMapImpl.GetterImpl
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImpleme

if ( valuesAccess != null ) {
final EmbeddableMappingType mappingType = runtimeDescriptorAccess.get();
mappingType.setPropertyValues( dataMap, valuesAccess.get() );
mappingType.setValues( dataMap, valuesAccess.get() );
}

return dataMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public EmbeddableInstantiatorPojoOptimized(
public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) {
final Object embeddable = instantiationOptimizer.newInstance();
final EmbeddableMappingType embeddableMapping = embeddableMappingAccess.get();
embeddableMapping.setPropertyValues( embeddable, valuesAccess.get() );
embeddableMapping.setValues( embeddable, valuesAccess.get() );
return embeddable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImpleme
// A possible alternative could be to initialize the resolved values for primitive fields to their default value,
// but that might cause unexpected outcomes for Hibernate 5 users that use createEmptyCompositesEnabled when updating.
// You can see the need for this by running EmptyCompositeEquivalentToNullTest
embeddableMappingAccess.get().setPropertyValues( instance, valuesAccess.get() );
embeddableMappingAccess.get().setValues( instance, valuesAccess.get() );
}

return instance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,12 @@ default String getPartName() {
/**
* Convenient access to getting the value for this attribute from the "owner"
*/
default Object getValue(Object container, SharedSessionContractImplementor session) {
return getValue( container, session.getSessionFactory() );
}

/**
* Convenient access to getting the value for this attribute from the "owner"
*/
default Object getValue(Object container, SessionFactoryImplementor sessionFactory) {
default Object getValue(Object container) {
return getPropertyAccess().getGetter().get( container );
}

default void setValue(Object container, Object value, SharedSessionContractImplementor session) {
setValue( container, value, session.getSessionFactory() );
}

default void setValue(Object container, Object value, SessionFactoryImplementor sessionFactory) {
getPropertyAccess().getSetter().set( container, value, sessionFactory );
default void setValue(Object container, Object value) {
getPropertyAccess().getSetter().set( container, value );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,17 @@ default void forEachAttributeMapping(IndexedConsumer<AttributeMapping> consumer)
}
}

Object[] getPropertyValues(Object compositeInstance);
Object[] getValues(Object instance);

void setPropertyValues(Object compositeInstance, Object[] resolvedValues);
default Object getValue(Object instance, int position) {
return getAttributeMapping( position ).getValue( instance );
}

void setValues(Object instance, Object[] resolvedValues);

default void setValue(Object instance, int position, Object value) {
getAttributeMapping( position ).setValue( instance, value );
}

/**
* @todo (6.0) : consider dropping this in favor of a form passing the ManagedMappingType
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.metamodel.mapping.internal;

import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.type.descriptor.java.JavaType;

/**
* Base support for EmbeddableMappingType implementations
*/
public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType {
protected final SessionFactoryImplementor sessionFactory;

public AbstractEmbeddableMapping(MappingModelCreationProcess creationProcess) {
this( creationProcess.getCreationContext() );
}

public AbstractEmbeddableMapping(RuntimeModelCreationContext creationContext) {
this( creationContext.getSessionFactory() );
}

protected AbstractEmbeddableMapping(SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
}

@Override
public JavaType<?> getMappedJavaTypeDescriptor() {
return getRepresentationStrategy().getMappedJavaTypeDescriptor();
}

@Override
public Object[] getValues(Object compositeInstance) {
if ( compositeInstance == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
return new Object[getNumberOfAttributeMappings()];
}

final ReflectionOptimizer optimizer = getRepresentationStrategy().getReflectionOptimizer();
if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
return optimizer.getAccessOptimizer().getPropertyValues( compositeInstance );
}

final Object[] results = new Object[getNumberOfAttributeMappings()];
forEachAttributeMapping( (position, attribute) -> {
final Getter getter = attribute.getAttributeMetadataAccess()
.resolveAttributeMetadata( null )
.getPropertyAccess()
.getGetter();
results[position] = getter.get( compositeInstance );
} );
return results;
}

@Override
public void setValues(Object component, Object[] values) {
final ReflectionOptimizer optimizer = getRepresentationStrategy().getReflectionOptimizer();
if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
optimizer.getAccessOptimizer().setPropertyValues( component, values );
}
else {
forEachAttributeMapping( (position, attribute) -> {
attribute.getPropertyAccess().getSetter().set( component, values[position] );
} );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public Object getIdentifier(Object entity, SharedSessionContractImplementor sess

@Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
propertyAccess.getSetter().set( entity, id, session.getFactory() );
propertyAccess.getSetter().set( entity, id );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.SharedSessionContract;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.FetchTiming;
Expand Down Expand Up @@ -50,14 +49,12 @@
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.Clause;
Expand All @@ -81,9 +78,12 @@
import org.hibernate.type.spi.TypeConfiguration;

/**
* @author Steve Ebersole
* Describes a "normal" embeddable.
*
* NOTE: At the moment, this class is used to describe some non-normal cases: mainly
* composite fks
*/
public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, SelectableMappings {
public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping implements SelectableMappings {

public static EmbeddableMappingTypeImpl from(
Component bootDescriptor,
Expand Down Expand Up @@ -150,8 +150,6 @@ public static EmbeddableMappingTypeImpl from(
private final JavaType<?> embeddableJtd;
private final EmbeddableRepresentationStrategy representationStrategy;

private final SessionFactoryImplementor sessionFactory;

private final List<AttributeMapping> attributeMappings = new ArrayList<>();
private SelectableMappings selectableMappings;

Expand All @@ -163,14 +161,13 @@ private EmbeddableMappingTypeImpl(
Component bootDescriptor,
Function<EmbeddableMappingType, EmbeddableValuedModelPart> embeddedPartBuilder,
RuntimeModelCreationContext creationContext) {
super( creationContext );
this.representationStrategy = creationContext
.getBootstrapContext()
.getRepresentationStrategySelector()
.resolveStrategy( bootDescriptor, () -> this, creationContext );

this.embeddableJtd = representationStrategy.getMappedJavaTypeDescriptor();
this.sessionFactory = creationContext.getSessionFactory();

this.valueMapping = embeddedPartBuilder.apply( this );

final ConfigurationService cs = sessionFactory.getServiceRegistry()
Expand All @@ -190,9 +187,10 @@ public EmbeddableMappingTypeImpl(
SelectableMappings selectableMappings,
EmbeddableMappingType inverseMappingType,
MappingModelCreationProcess creationProcess) {
super( creationProcess );

this.embeddableJtd = inverseMappingType.getJavaTypeDescriptor();
this.representationStrategy = inverseMappingType.getRepresentationStrategy();
this.sessionFactory = creationProcess.getCreationContext().getSessionFactory();
this.valueMapping = valueMapping;
this.createEmptyCompositesEnabled = inverseMappingType.isCreateEmptyCompositesEnabled();
this.selectableMappings = selectableMappings;
Expand Down Expand Up @@ -787,35 +785,6 @@ public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatT
visitAttributeMappings( consumer );
}

public Object[] getPropertyValues(Object compositeInstance) {
final Object[] results = new Object[attributeMappings.size()];
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final StateArrayContributorMapping attr = (StateArrayContributorMapping) attributeMappings.get( i );
final Getter getter = attr.getAttributeMetadataAccess()
.resolveAttributeMetadata( null )
.getPropertyAccess()
.getGetter();
results[ attr.getStateArrayPosition() ] = getter.get( compositeInstance );
}
return results;
}

public void setPropertyValues(Object compositeInstance, Object[] resolvedValues) {
final ReflectionOptimizer reflectionOptimizer = representationStrategy.getReflectionOptimizer();
if ( reflectionOptimizer != null ) {
final ReflectionOptimizer.AccessOptimizer accessOptimizer = reflectionOptimizer.getAccessOptimizer();
if ( accessOptimizer != null ) {
accessOptimizer.setPropertyValues( compositeInstance, resolvedValues );
}
return;
}

for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
attributeMapping.setValue( compositeInstance, resolvedValues[i], sessionFactory );
}
}

public boolean isCreateEmptyCompositesEnabled() {
return createEmptyCompositesEnabled;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public Object getIdentifier(Object entity, SharedSessionContractImplementor sess

@Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
propertyAccess.getSetter().set( entity, id, session.getFactory() );
propertyAccess.getSetter().set( entity, id );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public Callback getCallback() {
.resolveAttributeMetadata( entityDescriptor )
.getPropertyAccess()
.getSetter()
.set( entity, generatedValue, sessionFactory );
.set( entity, generatedValue );
}
}

Expand Down

0 comments on commit b23c2f4

Please sign in to comment.