HHH-14950 - Support mapping of embeddables with no setters w/ custom instantiator

HHH-14964 - EmbeddableInitializer are called multiple times

HHH-14950 works for the most part, but cannot be used "for real" because of HHH-14964
This commit is contained in:
Steve Ebersole 2021-12-08 23:19:06 -06:00
parent a2a6425b82
commit 1e4f1fef44
41 changed files with 131 additions and 81 deletions

View File

@ -251,7 +251,7 @@ public final class ReflectHelper {
} }
private static Getter getter(Class clazz, String name) throws MappingException { private static Getter getter(Class clazz, String name) throws MappingException {
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name ).getGetter(); return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name, true ).getGetter();
} }
public static Object getConstantValue(String name, SessionFactoryImplementor factory) { public static Object getConstantValue(String name, SessionFactoryImplementor factory) {

View File

@ -444,7 +444,7 @@ public class Component extends SimpleValue implements MetaAttributable {
private Setter injector(Property property, Class attributeDeclarer) { private Setter injector(Property property, Class attributeDeclarer) {
return property.getPropertyAccessStrategy( attributeDeclarer ) return property.getPropertyAccessStrategy( attributeDeclarer )
.buildPropertyAccess( attributeDeclarer, property.getName() ) .buildPropertyAccess( attributeDeclarer, property.getName(), true )
.getSetter(); .getSetter();
} }

View File

@ -327,12 +327,12 @@ public class Property implements Serializable, MetaAttributable {
// todo : remove // todo : remove
public Getter getGetter(Class clazz) throws PropertyNotFoundException, MappingException { public Getter getGetter(Class clazz) throws PropertyNotFoundException, MappingException {
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name ).getGetter(); return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getGetter();
} }
// todo : remove // todo : remove
public Setter getSetter(Class clazz) throws PropertyNotFoundException, MappingException { public Setter getSetter(Class clazz) throws PropertyNotFoundException, MappingException {
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name ).getSetter(); return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getSetter();
} }
// todo : remove // todo : remove

View File

@ -58,8 +58,8 @@ public class EmbeddableRepresentationStrategyMap implements EmbeddableRepresenta
public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) { public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) {
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null, null,
bootAttributeDescriptor.getName() bootAttributeDescriptor.getName(),
); true );
} }
@Override @Override

View File

@ -151,7 +151,8 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr
return strategy.buildPropertyAccess( return strategy.buildPropertyAccess(
getEmbeddableJavaTypeDescriptor().getJavaTypeClass(), getEmbeddableJavaTypeDescriptor().getJavaTypeClass(),
bootAttributeDescriptor.getName() bootAttributeDescriptor.getName(),
instantiator instanceof StandardEmbeddableInstantiator
); );
} }

View File

@ -59,8 +59,8 @@ public class EntityRepresentationStrategyMap implements EntityRepresentationStra
final Property property = itr.next(); final Property property = itr.next();
final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null, null,
property.getName() property.getName(),
); true );
propertyAccessMap.put( property.getName(), propertyAccess ); propertyAccessMap.put( property.getName(), propertyAccess );
@ -105,8 +105,8 @@ public class EntityRepresentationStrategyMap implements EntityRepresentationStra
public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) { public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) {
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null, null,
bootAttributeDescriptor.getName() bootAttributeDescriptor.getName(),
); true );
} }
@Override @Override

View File

@ -384,7 +384,7 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent
); );
} }
return strategy.buildPropertyAccess( mappedJtd.getJavaTypeClass(), bootAttributeDescriptor.getName() ); return strategy.buildPropertyAccess( mappedJtd.getJavaTypeClass(), bootAttributeDescriptor.getName(), true );
} }
@Override @Override

View File

@ -402,8 +402,8 @@ public class EmbeddedAttributeMapping
if ( parentInjectionAttributeName != null ) { if ( parentInjectionAttributeName != null ) {
parentInjectionAttributePropertyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess( parentInjectionAttributePropertyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess(
embeddableMappingType.getMappedJavaTypeDescriptor().getJavaTypeClass(), embeddableMappingType.getMappedJavaTypeDescriptor().getJavaTypeClass(),
parentInjectionAttributeName parentInjectionAttributeName,
); true );
} }
else { else {
parentInjectionAttributePropertyAccess = null; parentInjectionAttributePropertyAccess = null;

View File

@ -82,8 +82,8 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
if ( parentInjectionAttributeName != null ) { if ( parentInjectionAttributeName != null ) {
parentInjectionAttributePropertyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess( parentInjectionAttributePropertyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess(
embeddableMappingType.getMappedJavaTypeDescriptor().getJavaTypeClass(), embeddableMappingType.getMappedJavaTypeDescriptor().getJavaTypeClass(),
parentInjectionAttributeName parentInjectionAttributeName,
); true );
} }
else { else {
parentInjectionAttributePropertyAccess = null; parentInjectionAttributePropertyAccess = null;

View File

@ -97,8 +97,8 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null, null,
EntityIdentifierMapping.ROLE_LOCAL_NAME EntityIdentifierMapping.ROLE_LOCAL_NAME,
); true );
final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess( final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess(
propertyAccess propertyAccess
); );

View File

@ -52,7 +52,7 @@ public class IdClassRepresentationStrategy implements EmbeddableRepresentationSt
public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) { public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) {
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess(
idClassType.getJavaTypeClass(), idClassType.getJavaTypeClass(),
bootAttributeDescriptor.getName() bootAttributeDescriptor.getName(),
); true );
} }
} }

View File

@ -34,15 +34,24 @@ public class PropertyAccessBasicImpl implements PropertyAccess {
public PropertyAccessBasicImpl( public PropertyAccessBasicImpl(
PropertyAccessStrategyBasicImpl strategy, PropertyAccessStrategyBasicImpl strategy,
Class containerJavaType, Class<?> containerJavaType,
final String propertyName) { final String propertyName,
boolean setterRequired) {
this.strategy = strategy; this.strategy = strategy;
final Method getterMethod = ReflectHelper.findGetterMethod( containerJavaType, propertyName ); final Method getterMethod = ReflectHelper.findGetterMethod( containerJavaType, propertyName );
this.getter = new GetterMethodImpl( containerJavaType, propertyName, getterMethod ); this.getter = new GetterMethodImpl( containerJavaType, propertyName, getterMethod );
final Method setterMethod = ReflectHelper.findSetterMethod( containerJavaType, propertyName, getterMethod.getReturnType() ); final Method setterMethod;
this.setter = new SetterMethodImpl( containerJavaType, propertyName, setterMethod ); if ( setterRequired ) {
setterMethod = ReflectHelper.findSetterMethod( containerJavaType, propertyName, getterMethod.getReturnType() );
}
else {
setterMethod = ReflectHelper.setterMethodOrNull( containerJavaType, propertyName, getterMethod.getReturnType() );
}
this.setter = setterMethod != null
? new SetterMethodImpl( containerJavaType, propertyName, setterMethod )
: null;
} }
@Override @Override

View File

@ -47,7 +47,7 @@ public class PropertyAccessStrategyBackRefImpl implements PropertyAccessStrategy
} }
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessBackRefImpl( this ); return new PropertyAccessBackRefImpl( this );
} }

View File

@ -23,7 +23,7 @@ public class PropertyAccessStrategyBasicImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyBasicImpl INSTANCE = new PropertyAccessStrategyBasicImpl(); public static final PropertyAccessStrategyBasicImpl INSTANCE = new PropertyAccessStrategyBasicImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, final String propertyName) { public PropertyAccess buildPropertyAccess(Class<?> containerJavaType, final String propertyName, boolean setterRequired) {
return new PropertyAccessBasicImpl( this, containerJavaType, propertyName ); return new PropertyAccessBasicImpl( this, containerJavaType, propertyName, setterRequired );
} }
} }

View File

@ -22,10 +22,10 @@ public class PropertyAccessStrategyChainedImpl implements PropertyAccessStrategy
} }
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
for ( PropertyAccessStrategy candidate : chain ) { for ( PropertyAccessStrategy candidate : chain ) {
try { try {
return candidate.buildPropertyAccess( containerJavaType, propertyName ); return candidate.buildPropertyAccess( containerJavaType, propertyName, true );
} }
catch (Exception ignore) { catch (Exception ignore) {
// ignore // ignore

View File

@ -22,7 +22,7 @@ public class PropertyAccessStrategyEmbeddedImpl implements PropertyAccessStrateg
public static final PropertyAccessStrategyEmbeddedImpl INSTANCE = new PropertyAccessStrategyEmbeddedImpl(); public static final PropertyAccessStrategyEmbeddedImpl INSTANCE = new PropertyAccessStrategyEmbeddedImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessEmbeddedImpl( this, containerJavaType, propertyName ); return new PropertyAccessEmbeddedImpl( this, containerJavaType, propertyName );
} }
} }

View File

@ -23,7 +23,7 @@ public class PropertyAccessStrategyEnhancedImpl implements PropertyAccessStrateg
public static final PropertyAccessStrategyEnhancedImpl INSTANCE = new PropertyAccessStrategyEnhancedImpl(); public static final PropertyAccessStrategyEnhancedImpl INSTANCE = new PropertyAccessStrategyEnhancedImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, final String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, final String propertyName, boolean setterRequired) {
return new PropertyAccessEnhancedImpl( this, containerJavaType, propertyName ); return new PropertyAccessEnhancedImpl( this, containerJavaType, propertyName );
} }
} }

View File

@ -22,7 +22,7 @@ public class PropertyAccessStrategyFieldImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyFieldImpl INSTANCE = new PropertyAccessStrategyFieldImpl(); public static final PropertyAccessStrategyFieldImpl INSTANCE = new PropertyAccessStrategyFieldImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessFieldImpl( this, containerJavaType, propertyName ); return new PropertyAccessFieldImpl( this, containerJavaType, propertyName );
} }
} }

View File

@ -31,7 +31,7 @@ public class PropertyAccessStrategyIndexBackRefImpl implements PropertyAccessStr
} }
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessIndexBackRefImpl( this ); return new PropertyAccessIndexBackRefImpl( this );
} }

View File

@ -21,7 +21,7 @@ public class PropertyAccessStrategyMapImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyMapImpl INSTANCE = new PropertyAccessStrategyMapImpl(); public static final PropertyAccessStrategyMapImpl INSTANCE = new PropertyAccessStrategyMapImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
// Sometimes containerJavaType is null, but if it isn't, make sure it's a Map. // Sometimes containerJavaType is null, but if it isn't, make sure it's a Map.
if (containerJavaType != null && !Map.class.isAssignableFrom(containerJavaType)) { if (containerJavaType != null && !Map.class.isAssignableFrom(containerJavaType)) {

View File

@ -21,7 +21,7 @@ public class PropertyAccessStrategyMixedImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyMixedImpl INSTANCE = new PropertyAccessStrategyMixedImpl(); public static final PropertyAccessStrategyMixedImpl INSTANCE = new PropertyAccessStrategyMixedImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessMixedImpl( this, containerJavaType, propertyName ); return new PropertyAccessMixedImpl( this, containerJavaType, propertyName );
} }
} }

View File

@ -31,7 +31,7 @@ public class PropertyAccessStrategyNoopImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyNoopImpl INSTANCE = new PropertyAccessStrategyNoopImpl(); public static final PropertyAccessStrategyNoopImpl INSTANCE = new PropertyAccessStrategyNoopImpl();
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return PropertyAccessNoopImpl.INSTANCE; return PropertyAccessNoopImpl.INSTANCE;
} }

View File

@ -8,9 +8,8 @@ package org.hibernate.property.access.spi;
/** /**
* Describes a strategy for persistent property access (field, JavaBean-style property, etc). * Describes a strategy for persistent property access (field, JavaBean-style property, etc).
* Acts as a factory for {@link PropertyAccess} instances.
* *
* @author Steve Ebersole * Acts as a factory for {@link PropertyAccess} instances.
*/ */
public interface PropertyAccessStrategy { public interface PropertyAccessStrategy {
/** /**
@ -18,8 +17,9 @@ public interface PropertyAccessStrategy {
* *
* @param containerJavaType The Java type that contains the property; may be {@code null} for non-pojo cases. * @param containerJavaType The Java type that contains the property; may be {@code null} for non-pojo cases.
* @param propertyName The property name * @param propertyName The property name
* @param setterRequired Whether it is an error if we are unable to find a corresponding setter
* *
* @return The appropriate PropertyAccess * @return The appropriate PropertyAccess
*/ */
PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName); PropertyAccess buildPropertyAccess(Class<?> containerJavaType, String propertyName, boolean setterRequired);
} }

View File

@ -9,8 +9,6 @@ package org.hibernate.property.access.spi;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/** /**
* The contract for setting a persistent property value into its container/owner * The contract for setting a persistent property value into its container/owner
* *

View File

@ -1366,8 +1366,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
try { try {
final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess( final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess(
clazz, clazz,
paramName paramName,
); true );
final Getter getter = propertyAccess.getGetter(); final Getter getter = propertyAccess.getGetter();
final Class<?> retType = getter.getReturnTypeClass(); final Class<?> retType = getter.getReturnTypeClass();
final Object object = getter.get( bean ); final Object object = getter.get( bean );

View File

@ -140,13 +140,11 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override @Override
public void resolveKey(RowProcessingState processingState) { public void resolveKey(RowProcessingState processingState) {
// nothing to do // nothing to do
EmbeddableLoadingLogger.INSTANCE.debugf( "EmbeddableInitializer#resolveKey : %s", navigablePath.getFullPath() );
} }
@Override @Override
public void resolveInstance(RowProcessingState processingState) { public void resolveInstance(RowProcessingState processingState) {
// nothing to do // nothing to do
EmbeddableLoadingLogger.INSTANCE.debugf( "EmbeddableInitializer#resolveInstance : %s", navigablePath.getFullPath() );
} }
@Override @Override

View File

@ -108,14 +108,9 @@ public class StandardRowReader<T> implements RowReader<T> {
private void afterRow(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { private void afterRow(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
LoadingLogger.LOGGER.trace( "StandardRowReader#afterRow" ); LoadingLogger.LOGGER.trace( "StandardRowReader#afterRow" );
// todo (6.0) : add AfterLoadActions handling here via Callback initializers.forEach( (initializer) -> {
//
// maybe :
// initializer.finishUpRow( rowProcessingState, callback );
for ( Initializer initializer : initializers ) {
initializer.finishUpRow( rowProcessingState ); initializer.finishUpRow( rowProcessingState );
} } );
} }
@SuppressWarnings("ForLoopReplaceableByForEach") @SuppressWarnings("ForLoopReplaceableByForEach")

View File

@ -98,7 +98,7 @@ public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransf
String alias = aliases[ i ]; String alias = aliases[ i ];
if ( alias != null ) { if ( alias != null ) {
this.aliases[ i ] = alias; this.aliases[ i ] = alias;
setters[ i ] = propertyAccessStrategy.buildPropertyAccess( resultClass, alias ).getSetter(); setters[ i ] = propertyAccessStrategy.buildPropertyAccess( resultClass, alias, true ).getSetter();
} }
} }
isInitialized = true; isInitialized = true;

View File

@ -319,8 +319,8 @@ public final class PropertyFactory {
final PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess( final PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess(
mappingProperty.getPersistentClass().getMappedClass(), mappingProperty.getPersistentClass().getMappedClass(),
mappingProperty.getName() mappingProperty.getName(),
); true );
return propertyAccess.getGetter(); return propertyAccess.getGetter();
} }

View File

@ -38,10 +38,10 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
private PropertyAccess buildPropertyAccess(Property mappedProperty) { private PropertyAccess buildPropertyAccess(Property mappedProperty) {
if ( mappedProperty.isBackRef() ) { if ( mappedProperty.isBackRef() ) {
return mappedProperty.getPropertyAccessStrategy( null ).buildPropertyAccess( null, mappedProperty.getName() ); return mappedProperty.getPropertyAccessStrategy( null ).buildPropertyAccess( null, mappedProperty.getName(), true );
} }
else { else {
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( null, mappedProperty.getName() ); return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( null, mappedProperty.getName(), true );
} }
} }

View File

@ -95,8 +95,8 @@ public class AttributeAccessorTest {
public static class BasicAttributeAccessor extends PropertyAccessStrategyBasicImpl { public static class BasicAttributeAccessor extends PropertyAccessStrategyBasicImpl {
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return super.buildPropertyAccess( containerJavaType, propertyName ); return super.buildPropertyAccess( containerJavaType, propertyName, setterRequired );
} }
} }
} }

View File

@ -28,49 +28,49 @@ public class BeanReflectionHelper {
static { static {
final PropertyAccessStrategyBasicImpl propertyAccessStrategy = new PropertyAccessStrategyBasicImpl(); final PropertyAccessStrategyBasicImpl propertyAccessStrategy = new PropertyAccessStrategyBasicImpl();
PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someString" ); PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someString", true );
Getter getter = propertyAccess.getGetter(); Getter getter = propertyAccess.getGetter();
Setter setter = propertyAccess.getSetter(); Setter setter = propertyAccess.getSetter();
getterNames[0] = getter.getMethodName(); getterNames[0] = getter.getMethodName();
types[0] = getter.getReturnTypeClass(); types[0] = getter.getReturnTypeClass();
setterNames[0] = setter.getMethodName(); setterNames[0] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[1] = getter.getMethodName(); getterNames[1] = getter.getMethodName();
types[1] = getter.getReturnTypeClass(); types[1] = getter.getReturnTypeClass();
setterNames[1] = setter.getMethodName(); setterNames[1] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[2] = getter.getMethodName(); getterNames[2] = getter.getMethodName();
types[2] = getter.getReturnTypeClass(); types[2] = getter.getReturnTypeClass();
setterNames[2] = setter.getMethodName(); setterNames[2] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[3] = getter.getMethodName(); getterNames[3] = getter.getMethodName();
types[3] = getter.getReturnTypeClass(); types[3] = getter.getReturnTypeClass();
setterNames[3] = setter.getMethodName(); setterNames[3] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[4] = getter.getMethodName(); getterNames[4] = getter.getMethodName();
types[4] = getter.getReturnTypeClass(); types[4] = getter.getReturnTypeClass();
setterNames[4] = setter.getMethodName(); setterNames[4] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[5] = getter.getMethodName(); getterNames[5] = getter.getMethodName();
types[5] = getter.getReturnTypeClass(); types[5] = getter.getReturnTypeClass();
setterNames[5] = setter.getMethodName(); setterNames[5] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject", true );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[6] = getter.getMethodName(); getterNames[6] = getter.getMethodName();

View File

@ -9,6 +9,13 @@ package org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.metamodel.EmbeddableRepresentationStrategy;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.RuntimeMetamodels;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope; import org.hibernate.testing.orm.junit.DomainModelScope;
@ -31,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@JiraKey( "HHH-14950" ) @JiraKey( "HHH-14950" )
public class InstantiationTests { public class InstantiationTests {
@Test @Test
public void modelTest(DomainModelScope scope) { public void bootModelTest(DomainModelScope scope) {
scope.withHierarchy( Person.class, (personMapping) -> { scope.withHierarchy( Person.class, (personMapping) -> {
final Property name = personMapping.getProperty( "name" ); final Property name = personMapping.getProperty( "name" );
final Component nameMapping = (Component) name.getValue(); final Component nameMapping = (Component) name.getValue();
@ -44,7 +51,23 @@ public class InstantiationTests {
} }
@Test @Test
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" ) public void runtimeModelTest(SessionFactoryScope scope) {
final RuntimeMetamodels runtimeMetamodels = scope.getSessionFactory().getRuntimeMetamodels();
final MappingMetamodel mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
final EntityPersister entityDescriptor = mappingMetamodel.findEntityDescriptor( Person.class );
final EmbeddedAttributeMapping nameEmbedded = (EmbeddedAttributeMapping) entityDescriptor.findAttributeMapping( "name" );
final EmbeddableMappingType nameEmbeddable = nameEmbedded.getEmbeddableTypeDescriptor();
final EmbeddableRepresentationStrategy nameRepStrategy = nameEmbeddable.getRepresentationStrategy();
assertThat( nameRepStrategy.getMode() ).isEqualTo( RepresentationMode.POJO );
assertThat( nameRepStrategy.getInstantiator() ).isInstanceOf( NameInstantiator.class );
nameEmbeddable.forEachAttributeMapping( (position, attribute) -> {
assertThat( attribute.getPropertyAccess().getSetter() ).isNull();
} );
}
@Test
@FailureExpected( jiraKey = "HHH-14964", reason = "EmbeddableInitializer is called twice, causing problems" )
public void basicTest(SessionFactoryScope scope) { public void basicTest(SessionFactoryScope scope) {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final Person mick = new Person( 1, new NameImpl( "Mick", "Jagger" ) ); final Person mick = new Person( 1, new NameImpl( "Mick", "Jagger" ) );

View File

@ -9,6 +9,13 @@ package org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf2;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.metamodel.EmbeddableRepresentationStrategy;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.RuntimeMetamodels;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope; import org.hibernate.testing.orm.junit.DomainModelScope;
@ -34,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@JiraKey( "HHH-14950" ) @JiraKey( "HHH-14950" )
public class InstantiationTests { public class InstantiationTests {
@Test @Test
public void modelTest(DomainModelScope scope) { public void bootModelTest(DomainModelScope scope) {
scope.withHierarchy( Person.class, (personMapping) -> { scope.withHierarchy( Person.class, (personMapping) -> {
final Property name = personMapping.getProperty( "name" ); final Property name = personMapping.getProperty( "name" );
final Component nameMapping = (Component) name.getValue(); final Component nameMapping = (Component) name.getValue();
@ -47,7 +54,23 @@ public class InstantiationTests {
} }
@Test @Test
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" ) public void runtimeModelTest(SessionFactoryScope scope) {
final RuntimeMetamodels runtimeMetamodels = scope.getSessionFactory().getRuntimeMetamodels();
final MappingMetamodel mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
final EntityPersister entityDescriptor = mappingMetamodel.findEntityDescriptor( Person.class );
final EmbeddedAttributeMapping nameEmbedded = (EmbeddedAttributeMapping) entityDescriptor.findAttributeMapping( "name" );
final EmbeddableMappingType nameEmbeddable = nameEmbedded.getEmbeddableTypeDescriptor();
final EmbeddableRepresentationStrategy nameRepStrategy = nameEmbeddable.getRepresentationStrategy();
assertThat( nameRepStrategy.getMode() ).isEqualTo( RepresentationMode.POJO );
assertThat( nameRepStrategy.getInstantiator() ).isInstanceOf( NameInstantiator.class );
nameEmbeddable.forEachAttributeMapping( (position, attribute) -> {
assertThat( attribute.getPropertyAccess().getSetter() ).isNull();
} );
}
@Test
@FailureExpected( jiraKey = "HHH-14964", reason = "EmbeddableInitializer is called twice, causing problems" )
public void basicTest(SessionFactoryScope scope) { public void basicTest(SessionFactoryScope scope) {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final Person mick = new Person( 1, Name.make( "Mick", "Jagger" ) ); final Person mick = new Person( 1, Name.make( "Mick", "Jagger" ) );

View File

@ -23,10 +23,10 @@ public class Name {
} }
String getFirstName() { String getFirstName() {
return "John"; return first;
} }
String getLastName() { String getLastName() {
return "Doe"; return last;
} }
} }

View File

@ -15,8 +15,11 @@ import org.hibernate.metamodel.EmbeddableInstantiator;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NameInstantiator implements EmbeddableInstantiator { public class NameInstantiator implements EmbeddableInstantiator {
public static int callCount = 0;
@Override @Override
public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) { public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) {
callCount++;
final Object[] values = valuesAccess.get(); final Object[] values = valuesAccess.get();
return Name.make( (String) values[0], (String) values[1] ); return Name.make( (String) values[0], (String) values[1] );
} }

View File

@ -73,13 +73,13 @@ public class BasicPropertyAccessorTest extends BaseUnitTestCase {
PropertyAccessStrategyBasicImpl accessStrategy = PropertyAccessStrategyBasicImpl.INSTANCE; PropertyAccessStrategyBasicImpl accessStrategy = PropertyAccessStrategyBasicImpl.INSTANCE;
{ {
final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper.class, "it" ); final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper.class, "it", true );
assertEquals( String.class, access.getGetter().getReturnTypeClass() ); assertEquals( String.class, access.getGetter().getReturnTypeClass() );
assertEquals( Object.class, access.getSetter().getMethod().getParameterTypes()[0] ); assertEquals( Object.class, access.getSetter().getMethod().getParameterTypes()[0] );
} }
{ {
final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper2.class, "it" ); final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper2.class, "it", true );
assertEquals( String.class, access.getGetter().getReturnTypeClass() ); assertEquals( String.class, access.getGetter().getReturnTypeClass() );
assertEquals( String.class, access.getSetter().getMethod().getParameterTypes()[0] ); assertEquals( String.class, access.getSetter().getMethod().getParameterTypes()[0] );
} }

View File

@ -36,7 +36,7 @@ public class PropertyAccessStrategyMapTest extends BaseUnitTestCase {
final PropertyAccessStrategyMapImpl accessStrategy = PropertyAccessStrategyMapImpl.INSTANCE; final PropertyAccessStrategyMapImpl accessStrategy = PropertyAccessStrategyMapImpl.INSTANCE;
try { try {
accessStrategy.buildPropertyAccess( Date.class, "time" ); accessStrategy.buildPropertyAccess( Date.class, "time", true );
fail("Should throw IllegalArgumentException"); fail("Should throw IllegalArgumentException");
} }
@ -54,7 +54,7 @@ public class PropertyAccessStrategyMapTest extends BaseUnitTestCase {
final String value = "testValue"; final String value = "testValue";
final PropertyAccessStrategyMapImpl accessStrategy = PropertyAccessStrategyMapImpl.INSTANCE; final PropertyAccessStrategyMapImpl accessStrategy = PropertyAccessStrategyMapImpl.INSTANCE;
final PropertyAccess access = accessStrategy.buildPropertyAccess( clazz, key ); final PropertyAccess access = accessStrategy.buildPropertyAccess( clazz, key, true );
final HashMap<String, String> map = new HashMap<>(); final HashMap<String, String> map = new HashMap<>();

View File

@ -54,7 +54,7 @@ logger.tooling-schema-script-graph.appenderRef.subsystem.ref=subsystem
# Logging related to the creation of DomainResult/Fetch graphs # Logging related to the creation of DomainResult/Fetch graphs
logger.sql-result-graph.name=org.hibernate.orm.sql.results logger.sql-result-graph.name=org.hibernate.orm.sql.results
logger.sql-result-graph.appenderRef.subsystem.ref=subsystem logger.sql-result-graph.appenderRef.subsystem.ref=subsystem
#logger.sql-result-graph.level=debug logger.sql-result-graph.level=debug
# Logs generated DomainResult/Fetch AST graph # Logs generated DomainResult/Fetch AST graph
logger.sql-result-ast.name=org.hibernate.orm.sql.results.graph.AST logger.sql-result-ast.name=org.hibernate.orm.sql.results.graph.AST

View File

@ -54,7 +54,7 @@ public abstract class ReflectionTools {
final Pair<Class, String> key = Pair.make( cls, propertyName ); final Pair<Class, String> key = Pair.make( cls, propertyName );
Getter value = GETTER_CACHE.get( key ); Getter value = GETTER_CACHE.get( key );
if ( value == null ) { if ( value == null ) {
value = getAccessStrategy( cls, serviceRegistry, accessorType ).buildPropertyAccess( cls, propertyName ).getGetter(); value = getAccessStrategy( cls, serviceRegistry, accessorType ).buildPropertyAccess( cls, propertyName, true ).getGetter();
// It's ok if two getters are generated concurrently // It's ok if two getters are generated concurrently
GETTER_CACHE.put( key, value ); GETTER_CACHE.put( key, value );
} }
@ -70,7 +70,7 @@ public abstract class ReflectionTools {
final Pair<Class, String> key = Pair.make( cls, propertyName ); final Pair<Class, String> key = Pair.make( cls, propertyName );
Setter value = SETTER_CACHE.get( key ); Setter value = SETTER_CACHE.get( key );
if ( value == null ) { if ( value == null ) {
value = getAccessStrategy( cls, serviceRegistry, accessorType ).buildPropertyAccess( cls, propertyName ).getSetter(); value = getAccessStrategy( cls, serviceRegistry, accessorType ).buildPropertyAccess( cls, propertyName, true ).getSetter();
// It's ok if two setters are generated concurrently // It's ok if two setters are generated concurrently
SETTER_CACHE.put( key, value ); SETTER_CACHE.put( key, value );
} }

View File

@ -91,9 +91,9 @@ public class AttributeAccessorTest extends BaseEnversJPAFunctionalTestCase {
public static class BasicAttributeAccessor extends PropertyAccessStrategyBasicImpl { public static class BasicAttributeAccessor extends PropertyAccessStrategyBasicImpl {
static boolean invoked; static boolean invoked;
@Override @Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
invoked = true; invoked = true;
return super.buildPropertyAccess( containerJavaType, propertyName ); return super.buildPropertyAccess( containerJavaType, propertyName, setterRequired );
} }
} }
} }