Clean up various legacy "read path" contracts

- clean-up unused Type methods
    * Type#nullSafeGet
    * Type#hydrate
    * Type#resolve
    * Type#getSemiResolvedType
    * Type#semiResolve
    * related
- start removing usage of Tuplizer
- start removing usage of legacy Tuplizer-based Instantiator
- drop `EntityMode` completely
- preliminary clean-up of EntityTuplizer
- preliminary clean-up of ComponentTuplizer
This commit is contained in:
Steve Ebersole 2021-10-21 16:25:50 -05:00
parent c34ea34f6b
commit b5558307a9
9 changed files with 36 additions and 345 deletions

View File

@ -46,6 +46,7 @@ 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;
@ -64,6 +65,7 @@ import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.spi.CompositeTypeImplementor;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -99,6 +101,10 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp
creationContext.getSessionFactory()
);
if ( compositeType instanceof CompositeTypeImplementor ) {
( (CompositeTypeImplementor) compositeType ).injectMappingModelPart( mappingType.getEmbeddedValueMapping(), creationProcess );
}
creationProcess.registerInitializationCallback(
"EmbeddableMappingType(" + mappingType.getNavigableRole().getFullPath() + ")#finishInitialization",
() -> {
@ -752,6 +758,19 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp
visitAttributeMappings( consumer::accept );
}
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) {
// todo (6.0) : reflection optimizer...
for ( int i = 0; i < attributeMappings.size(); i++ ) {

View File

@ -9,7 +9,6 @@ import java.lang.reflect.Method;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property;
import org.hibernate.property.access.spi.Getter;
@ -80,22 +79,10 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer {
return instantiator.instantiate();
}
public Object getParent(Object component) {
return null;
}
public boolean hasParentProperty() {
return false;
}
public boolean isMethodOf(Method method) {
return false;
}
public void setParent(Object component, Object parent, SessionFactoryImplementor factory) {
throw new UnsupportedOperationException();
}
public Getter getGetter(int i) {
return getters[i];
}

View File

@ -5,10 +5,10 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tuple.component;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.tuple.Tuplizer;
/**
@ -22,30 +22,6 @@ import org.hibernate.tuple.Tuplizer;
* @author Steve Ebersole
*/
public interface ComponentTuplizer extends Tuplizer, Serializable {
/**
* Retrieve the current value of the parent property.
*
* @param component The component instance from which to extract the parent
* property value.
* @return The current value of the parent property.
*/
public Object getParent(Object component);
/**
* Set the value of the parent property.
*
* @param component The component instance on which to set the parent.
* @param parent The parent to be set on the component.
* @param factory The current session factory.
*/
public void setParent(Object component, Object parent, SessionFactoryImplementor factory);
/**
* Does the component managed by this tuplizer contain a parent property?
*
* @return True if the component does contain a parent property; false otherwise.
*/
public boolean hasParentProperty();
/**
* Is the given method available via the managed component as a property getter?

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.tuple.component;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.hibernate.AssertionFailure;
@ -16,7 +15,6 @@ import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ProxyFactoryFactory;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property;
@ -102,14 +100,6 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
}
}
public Object getParent(Object component) {
return parentGetter.get( component );
}
public boolean hasParentProperty() {
return parentGetter != null;
}
public boolean isMethodOf(Method method) {
for ( int i = 0; i < propertySpan; i++ ) {
final Method getterMethod = getters[i].getMethod();
@ -120,10 +110,6 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
return false;
}
public void setParent(Object component, Object parent, SessionFactoryImplementor factory) {
parentSetter.set( component, parent, factory );
}
protected Instantiator buildInstantiator(Component component) {
if ( component.isEmbedded() && ReflectHelper.isAbstractClass( this.componentClass ) ) {
ProxyFactoryFactory proxyFactoryFactory = component.getServiceRegistry().getService( ProxyFactoryFactory.class );

View File

@ -21,7 +21,6 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
@ -196,11 +195,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
return entityMetamodel.getSubclassEntityNames();
}
@Override
public Object getIdentifier(Object entity) throws HibernateException {
return getIdentifier( entity, null );
}
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
final Object id;
@ -239,22 +233,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
}
@Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
if ( entity != id ) {
CompositeType copier = (CompositeType) entityMetamodel.getIdentifierProperty().getType();
copier.setPropertyValues( entity, copier.getPropertyValues( id ) );
}
}
else if ( idSetter != null ) {
idSetter.set( entity, id, getFactory() );
}
else if ( identifierMapperType != null ) {
mappedIdentifierValueMarshaller.setIdentifier( entity, id, session );
}
}
private interface MappedIdentifierValueMarshaller {
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
@ -488,14 +466,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
return metamodel.entityPersister( entityName );
}
@Override
public Object getVersion(Object entity) throws HibernateException {
if ( !entityMetamodel.isVersioned() ) {
return null;
}
return getters[entityMetamodel.getVersionPropertyIndex()].get( entity );
}
protected boolean shouldGetAllProperties(Object entity) {
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = getEntityMetamodel().getBytecodeEnhancementMetadata();
if ( !bytecodeEnhancementMetadata.isEnhancedForLazyLoading() ) {
@ -521,38 +491,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
return getters[i].get( entity );
}
@Override
public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException {
int loc = propertyPath.indexOf( '.' );
String basePropertyName = loc > 0
? propertyPath.substring( 0, loc )
: propertyPath;
//final int index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
Integer index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
if ( index == null ) {
propertyPath = PropertyPath.IDENTIFIER_MAPPER_PROPERTY + "." + propertyPath;
loc = propertyPath.indexOf( '.' );
basePropertyName = loc > 0
? propertyPath.substring( 0, loc )
: propertyPath;
}
index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
final Object baseValue = getPropertyValue( entity, index );
if ( loc > 0 ) {
if ( baseValue == null ) {
return null;
}
return getComponentValue(
(ComponentType) entityMetamodel.getPropertyTypes()[index],
baseValue,
propertyPath.substring( loc + 1 )
);
}
else {
return baseValue;
}
}
/**
* Extract a component property value.
*
@ -595,16 +533,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
throw new MappingException( "component property not found: " + subPropertyName );
}
@Override
public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
setters[i].set( entity, value, getFactory() );
}
@Override
public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
setters[entityMetamodel.getPropertyIndex( propertyName )].set( entity, value, getFactory() );
}
protected void linkToSession(Object entity, SharedSessionContractImplementor session) {
if ( session == null ) {
return;
@ -617,25 +545,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
}
@Override
public void afterInitialize(Object entity, SharedSessionContractImplementor session) {
}
@Override
public boolean hasProxy() {
return entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
}
@Override
public final Object createProxy(Object id, SharedSessionContractImplementor session) {
return getProxyFactory().getProxy( id, session );
}
@Override
public boolean isLifecycleImplementor() {
return false;
}
protected final EntityMetamodel getEntityMetamodel() {
return entityMetamodel;
}
@ -648,21 +557,11 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
return instantiator;
}
@Override
public final ProxyFactory getProxyFactory() {
return proxyFactory;
}
@Override
public String toString() {
return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
}
@Override
public Getter getIdentifierGetter() {
return idGetter;
}
@Override
public Getter getGetter(int i) {
return getters[i];

View File

@ -15,7 +15,6 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
@ -38,11 +37,6 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
super( entityMetamodel, mappedEntity );
}
@Override
public RepresentationMode getEntityMode() {
return RepresentationMode.MAP;
}
private PropertyAccess buildPropertyAccess(Property mappedProperty) {
if ( mappedProperty.isBackRef() ) {
return mappedProperty.getPropertyAccessStrategy( null ).buildPropertyAccess( null, mappedProperty.getName() );
@ -94,11 +88,6 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
return Map.class;
}
@Override
public Class getConcreteProxyClass() {
return Map.class;
}
@Override
public EntityNameResolver[] getEntityNameResolvers() {
return new EntityNameResolver[] {BasicEntityNameResolver.INSTANCE};

View File

@ -12,9 +12,6 @@ import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.tuple.Tuplizer;
/**
@ -32,31 +29,10 @@ import org.hibernate.tuple.Tuplizer;
*/
@Deprecated
public interface EntityTuplizer extends Tuplizer {
/**
* Return the entity-mode handled by this tuplizer instance.
*
* @return The entity-mode
*/
RepresentationMode getEntityMode();
/**
* Extract the identifier value from the given entity.
*
* @param entity The entity from which to extract the identifier value.
*
* @return The identifier value.
*
* @throws HibernateException If the entity does not define an identifier property, or an
* error occurs accessing its value.
*
* @deprecated Use {@link #getIdentifier(Object,SharedSessionContractImplementor)} instead.
*/
@Deprecated
Object getIdentifier(Object entity) throws HibernateException;
/**
* Extract the identifier value from the given entity.
*
* @param entity The entity from which to extract the identifier value.
* @param session The session from which is requests originates
*
@ -64,46 +40,6 @@ public interface EntityTuplizer extends Tuplizer {
*/
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
/**
* Inject the identifier value into the given entity.
* </p>
* Has no effect if the entity does not define an identifier property
*
* @param entity The entity to inject with the identifier value.
* @param id The value to be injected as the identifier.
* @param session The session from which is requests originates
*/
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
/**
* Extract the value of the version property from the given entity.
*
* @param entity The entity from which to extract the version value.
* @return The value of the version property, or null if not versioned.
* @throws HibernateException Indicates a problem accessing the version property
*/
Object getVersion(Object entity) throws HibernateException;
/**
* Inject the value of a particular property.
*
* @param entity The entity into which to inject the value.
* @param i The property's index.
* @param value The property value to inject.
* @throws HibernateException Indicates a problem access the property
*/
void setPropertyValue(Object entity, int i, Object value) throws HibernateException;
/**
* Inject the value of a particular property.
*
* @param entity The entity into which to inject the value.
* @param propertyName The name of the property.
* @param value The property value to inject.
* @throws HibernateException Indicates a problem access the property
*/
void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException;
/**
* Extract the values of the insertable properties of the entity (including backrefs)
*
@ -113,62 +49,7 @@ public interface EntityTuplizer extends Tuplizer {
* @return The insertable property values.
* @throws HibernateException Indicates a problem access the properties
*/
Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session)
throws HibernateException;
/**
* Extract the value of a particular property from the given entity.
*
* @param entity The entity from which to extract the property value.
* @param propertyName The name of the property for which to extract the value.
* @return The current value of the given property on the given entity.
* @throws HibernateException Indicates a problem access the property
*/
Object getPropertyValue(Object entity, String propertyName) throws HibernateException;
/**
* Called just after the entities properties have been initialized.
*
* @param entity The entity being initialized.
* @param session The session initializing this entity.
*/
void afterInitialize(Object entity, SharedSessionContractImplementor session);
/**
* Does this entity, for this mode, present a possibility for proxying?
*
* @return True if this tuplizer can generate proxies for this entity.
*/
boolean hasProxy();
/**
* Generates an appropriate proxy representation of this entity for this
* entity-mode.
*
* @param id The id of the instance for which to generate a proxy.
* @param session The session to which the proxy should be bound.
* @return The generate proxies.
* @throws HibernateException Indicates an error generating the proxy.
*/
Object createProxy(Object id, SharedSessionContractImplementor session) throws HibernateException;
/**
* Does the {@link #getMappedClass() class} managed by this tuplizer implement
* the {@link org.hibernate.classic.Lifecycle} interface.
*
* @return True if the Lifecycle interface is implemented; false otherwise.
*/
boolean isLifecycleImplementor();
/**
* Returns the java class to which generated proxies will be typed.
* <p/>
* todo : look at fully encapsulating {@link org.hibernate.engine.spi.PersistenceContext#narrowProxy} here,
* since that is the only external use of this method
*
* @return The java class to which generated proxies will be typed
*/
Class getConcreteProxyClass();
Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session);
/**
* Get any {@link EntityNameResolver EntityNameResolvers} associated with this {@link Tuplizer}.
@ -201,14 +82,4 @@ public interface EntityTuplizer extends Tuplizer {
*/
String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory);
/**
* Retrieve the getter for the identifier property. May return null.
*
* @return The getter for the identifier property.
*/
Getter getIdentifierGetter();
default ProxyFactory getProxyFactory() {
return null;
}
}

View File

@ -12,22 +12,17 @@ import java.util.Set;
import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ProxyFactoryFactory;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.cfg.Environment;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.proxy.ProxyFactory;
@ -149,21 +144,11 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
return optimizer.getAccessOptimizer().getPropertyValues( object );
}
@Override
public RepresentationMode getEntityMode() {
return RepresentationMode.POJO;
}
@Override
public Class getMappedClass() {
return mappedClass;
}
@Override
public boolean isLifecycleImplementor() {
return lifecycleImplementor;
}
@Override
protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
return mappedProperty.getGetter( mappedEntity.getMappedClass() );
@ -174,37 +159,8 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
return mappedProperty.getSetter( mappedEntity.getMappedClass() );
}
@Override
public Class getConcreteProxyClass() {
return proxyInterface;
}
//TODO: need to make the majority of this functionality into a top-level support class for custom impl support
@Override
public void afterInitialize(Object entity, SharedSessionContractImplementor session) {
if ( entity instanceof PersistentAttributeInterceptable ) {
final BytecodeLazyAttributeInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractLazyInterceptor( entity );
if ( interceptor == null || interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor(
entity,
getIdentifier( entity, session ),
session
);
}
else {
if ( interceptor.getLinkedSession() == null ) {
interceptor.setSession( session );
}
}
}
// clear the fields that are marked as dirty in the dirtiness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
}
@Override
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
if ( entityInstance == null ) {

View File

@ -29,6 +29,7 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.ValueGeneration;
import org.hibernate.tuple.component.ComponentMetamodel;
@ -481,8 +482,9 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
//not absolutely necessary, but helps for some
//equals()/hashCode() implementations
if ( componentTuplizer.hasParentProperty() ) {
componentTuplizer.setParent( result, componentTuplizer.getParent( component ), factory );
final PropertyAccess parentAccess = mappingModelPart().getParentInjectionAttributePropertyAccess();
if ( parentAccess != null ) {
parentAccess.getSetter().set( result, parentAccess.getGetter().get( component ), factory );
}
return result;
@ -559,13 +561,12 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
return componentTuplizer.instantiate();
}
public Object instantiate(Object parent, SharedSessionContractImplementor session)
throws HibernateException {
public Object instantiate(Object parent, SharedSessionContractImplementor session) {
Object result = instantiate();
if ( componentTuplizer.hasParentProperty() && parent != null ) {
componentTuplizer.setParent(
final PropertyAccess parentAccess = mappingModelPart().getParentInjectionAttributePropertyAccess();
if ( parentAccess != null && parent != null ) {
parentAccess.getSetter().set(
result,
session.getPersistenceContextInternal().proxyFor( parent ),
session.getFactory()
@ -817,4 +818,11 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
public EmbeddableValuedModelPart getMappingModelPart() {
return mappingModelPart;
}
public EmbeddableValuedModelPart mappingModelPart() {
if ( mappingModelPart == null ) {
throw new IllegalStateException( "Attempt to access EmbeddableValuedModelPart prior to its injection" );
}
return mappingModelPart;
}
}