diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java index 744c9eec1c..90725bd276 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java @@ -5,6 +5,7 @@ * See the lgpl.txt file in the root directory or . */ package org.hibernate.tuple.component; + import java.lang.reflect.Method; import java.util.Iterator; @@ -13,7 +14,6 @@ import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Setter; -import org.hibernate.tuple.Instantiator; /** * Support for tuplizers relating to components. @@ -25,10 +25,8 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { protected final Getter[] getters; protected final Setter[] setters; protected final int propertySpan; - protected final Instantiator instantiator; protected final boolean hasCustomAccessors; - protected abstract Instantiator buildInstantiator(Component component); protected abstract Getter buildGetter(Component component, Property prop); protected abstract Setter buildSetter(Component component, Property prop); @@ -51,7 +49,6 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { i++; } hasCustomAccessors = foundCustomAccessor; - instantiator = buildInstantiator( component ); } public Object getPropertyValue(Object component, int i) throws HibernateException { @@ -72,13 +69,6 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { } } - /** - * This method does not populate the component parent - */ - public Object instantiate() throws HibernateException { - return instantiator.instantiate(); - } - public boolean isMethodOf(Method method) { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java index ff7a24e56d..cb1de23729 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java @@ -35,13 +35,6 @@ public interface ComponentTuplizer extends Tuplizer, Serializable { */ public boolean isMethodOf(Method method); - /** - * Generate a new, empty entity. - * - * @return The new, empty entity instance. - */ - public Object instantiate(); - /** * Extract the current values contained on the given entity. * diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java index b1c012a95f..3253508221 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java @@ -12,8 +12,6 @@ import org.hibernate.mapping.Property; import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl; import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Setter; -import org.hibernate.tuple.DynamicMapInstantiator; -import org.hibernate.tuple.Instantiator; /** * A {@link ComponentTuplizer} specific to the dynamic-map entity mode. @@ -27,10 +25,6 @@ public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer { return Map.class; } - protected Instantiator buildInstantiator(Component component) { - return new DynamicMapInstantiator(); - } - public DynamicMapComponentTuplizer(Component component) { super(component); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java index 5c12e87e4a..576291df85 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java @@ -15,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.internal.util.ReflectHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl; @@ -24,7 +23,6 @@ import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.Setter; import org.hibernate.tuple.Instantiator; -import org.hibernate.tuple.PojoInstantiator; /** * A {@link ComponentTuplizer} specific to the pojo entity mode. @@ -110,19 +108,6 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { return false; } - protected Instantiator buildInstantiator(Component component) { - if ( component.isEmbedded() && ReflectHelper.isAbstractClass( this.componentClass ) ) { - ProxyFactoryFactory proxyFactoryFactory = component.getServiceRegistry().getService( ProxyFactoryFactory.class ); - return new ProxiedInstantiator( this.componentClass, proxyFactoryFactory ); - } - if ( optimizer == null ) { - return new PojoInstantiator( this.componentClass, null ); - } - else { - return new PojoInstantiator( this.componentClass, optimizer.getInstantiationOptimizer() ); - } - } - protected Getter buildGetter(Component component, Property prop) { return prop.getGetter( this.componentClass ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index cdbbd3df5f..e369059e1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -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.metamodel.spi.EmbeddableInstantiator; import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.tuple.StandardProperty; import org.hibernate.tuple.ValueGeneration; @@ -466,19 +467,20 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen } @Override - public Object deepCopy(Object component, SessionFactoryImplementor factory) - throws HibernateException { + public Object deepCopy(Object component, SessionFactoryImplementor factory) { if ( component == null ) { return null; } - Object[] values = getPropertyValues( component ); + final Object[] values = getPropertyValues( component ); for ( int i = 0; i < propertySpan; i++ ) { values[i] = propertyTypes[i].deepCopy( values[i], factory ); } - Object result = instantiate(); - setPropertyValues( result, values ); + final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator(); + Object result = instantiator.instantiate( () -> values, factory ); //not absolutely necessary, but helps for some //equals()/hashCode() implementations @@ -496,29 +498,42 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen Object target, SharedSessionContractImplementor session, Object owner, - Map copyCache) - throws HibernateException { + Map copyCache) { if ( original == null ) { return null; } //if ( original == target ) return target; - final Object result = target == null - ? instantiate( owner, session ) - : target; + final Object[] originalValues = getPropertyValues( original ); + final Object[] resultValues; - Object[] values = TypeHelper.replace( - getPropertyValues( original ), - getPropertyValues( result ), + if ( target == null ) { + resultValues = new Object[originalValues.length]; + } + else { + resultValues = getPropertyValues( target ); + } + + final Object[] replacedValues = TypeHelper.replace( + originalValues, + resultValues, propertyTypes, session, owner, copyCache ); - setPropertyValues( result, values ); - return result; + if ( target == null ) { + final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator(); + return instantiator.instantiate( () -> replacedValues, session.getSessionFactory() ); + } + else { + setPropertyValues( target, replacedValues ); + return target; + } } @Override @@ -528,21 +543,27 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen SharedSessionContractImplementor session, Object owner, Map copyCache, - ForeignKeyDirection foreignKeyDirection) - throws HibernateException { + ForeignKeyDirection foreignKeyDirection) { if ( original == null ) { return null; } //if ( original == target ) return target; - final Object result = target == null ? - instantiate( owner, session ) : - target; - Object[] values = TypeHelper.replace( - getPropertyValues( original ), - getPropertyValues( result ), + final Object[] originalValues = getPropertyValues( original ); + final Object[] resultValues; + + if ( target == null ) { + resultValues = new Object[originalValues.length]; + } + else { + resultValues = getPropertyValues( target ); + } + + final Object[] replacedValues = TypeHelper.replace( + originalValues, + resultValues, propertyTypes, session, owner, @@ -550,30 +571,16 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen foreignKeyDirection ); - setPropertyValues( result, values ); - return result; - } - - /** - * This method does not populate the component parent - */ - public Object instantiate() { - return componentTuplizer.instantiate(); - } - - public Object instantiate(Object parent, SharedSessionContractImplementor session) { - Object result = instantiate(); - - final PropertyAccess parentAccess = mappingModelPart().getParentInjectionAttributePropertyAccess(); - if ( parentAccess != null && parent != null ) { - parentAccess.getSetter().set( - result, - session.getPersistenceContextInternal().proxyFor( parent ), - session.getFactory() - ); + if ( target == null ) { + final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator(); + return instantiator.instantiate( () -> replacedValues, session.getSessionFactory() ); + } + else { + setPropertyValues( target, replacedValues ); + return target; } - - return result; } @Override @@ -615,9 +622,11 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen for ( int i = 0; i < propertyTypes.length; i++ ) { assembled[i] = propertyTypes[i].assemble( (Serializable) values[i], session, owner ); } - Object result = instantiate( owner, session ); - setPropertyValues( result, assembled ); - return result; + + final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator(); + return instantiator.instantiate( () -> assembled, session.getFactory() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/EmbeddedComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/EmbeddedComponentType.java index 88512fe1ad..c51b2e8311 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EmbeddedComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EmbeddedComponentType.java @@ -8,8 +8,6 @@ package org.hibernate.type; import java.lang.reflect.Method; -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.type.spi.TypeConfiguration; @@ -28,15 +26,4 @@ public class EmbeddedComponentType extends ComponentType { public boolean isMethodOf(Method method) { return componentTuplizer.isMethodOf( method ); } - - @Override - public Object instantiate(Object parent, SharedSessionContractImplementor session) throws HibernateException { - final boolean useParent = parent != null && - //TODO: Yuck! This is not quite good enough, it's a quick - //hack around the problem of having a to-one association - //that refers to an embedded component: - super.getReturnedClass().isInstance( parent ); - - return useParent ? parent : super.instantiate( parent, session ); - } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/component/proxy/ComponentBasicProxyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/component/proxy/ComponentBasicProxyTest.java index c73bc1beae..bd30927ca0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/component/proxy/ComponentBasicProxyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/component/proxy/ComponentBasicProxyTest.java @@ -8,43 +8,40 @@ package org.hibernate.orm.test.component.proxy; import java.util.List; -import org.hibernate.boot.Metadata; -import org.hibernate.boot.MetadataSources; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; -import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; -import org.hibernate.type.ComponentType; +import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; +import org.hibernate.metamodel.spi.EmbeddableInstantiator; +import org.hibernate.type.spi.CompositeTypeImplementor; import org.hibernate.testing.TestForIssue; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.DomainModelScope; +import org.hibernate.testing.orm.junit.NotImplementedYet; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; -import static org.junit.Assert.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Guillaume Smet * @author Oliver Libutzki */ -public class ComponentBasicProxyTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[]{ - Person.class, Adult.class - }; - } +@DomainModel( annotatedClasses = { Person.class, Adult.class } ) +@SessionFactory +public class ComponentBasicProxyTest { @Test @TestForIssue(jiraKey = "HHH-12786") - public void testBasicProxyingWithProtectedMethodCalledInConstructor() { - doInJPA( this::entityManagerFactory, entityManager -> { + public void testBasicProxyingWithProtectedMethodCalledInConstructor(SessionFactoryScope scope) { + scope.inTransaction( (entityManager) -> { Adult adult = new Adult(); adult.setName( "Arjun Kumar" ); entityManager.persist( adult ); } ); - doInJPA( this::entityManagerFactory, entityManager -> { + scope.inTransaction( (entityManager) -> { List adultsCalledArjun = entityManager .createQuery( "SELECT a from Adult a WHERE a.name = :name", Adult.class ) .setParameter( "name", "Arjun Kumar" ).getResultList(); @@ -55,25 +52,18 @@ public class ComponentBasicProxyTest extends BaseEntityManagerFunctionalTestCase @Test @TestForIssue(jiraKey = "HHH-12791") - public void testOnlyOneProxyClassGenerated() { - StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build(); + public void testOnlyOneProxyClassGenerated(DomainModelScope domainModelScope, SessionFactoryScope sfScope) { + final SessionFactoryImplementor sessionFactory = sfScope.getSessionFactory(); - try { - Metadata metadata = new MetadataSources( ssr ).addAnnotatedClass( Person.class ) - .getMetadataBuilder() - .build(); - PersistentClass persistentClass = metadata.getEntityBinding( Person.class.getName() ); + final PersistentClass personDescriptor = domainModelScope.getDomainModel().getEntityBinding( Person.class.getName() ); + final CompositeTypeImplementor componentType = (CompositeTypeImplementor) personDescriptor.getIdentifierMapper().getType(); + final EmbeddableValuedModelPart embedded = componentType.getMappingModelPart(); + final EmbeddableInstantiator instantiator = embedded.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator(); - ComponentType componentType1 = (ComponentType) persistentClass.getIdentifierMapper().getType(); - Object instance1 = componentType1.instantiate(); - - ComponentType componentType2 = (ComponentType) persistentClass.getIdentifierMapper().getType(); - Object instance2 = componentType2.instantiate(); - - assertEquals( instance1.getClass(), instance2.getClass() ); - } - finally { - StandardServiceRegistryBuilder.destroy( ssr ); - } + final Object instance1 = instantiator.instantiate( null, sessionFactory ); + final Object instance2 = instantiator.instantiate( null, sessionFactory ); + assertThat( instance1.getClass() ).isEqualTo( instance2.getClass() ); } }