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 {
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name ).getGetter();
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name, true ).getGetter();
}
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) {
return property.getPropertyAccessStrategy( attributeDeclarer )
.buildPropertyAccess( attributeDeclarer, property.getName() )
.buildPropertyAccess( attributeDeclarer, property.getName(), true )
.getSetter();
}

View File

@ -327,12 +327,12 @@ public class Property implements Serializable, MetaAttributable {
// todo : remove
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
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

View File

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

View File

@ -151,7 +151,8 @@ public class EmbeddableRepresentationStrategyPojo extends AbstractEmbeddableRepr
return strategy.buildPropertyAccess(
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 PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null,
property.getName()
);
property.getName(),
true );
propertyAccessMap.put( property.getName(), propertyAccess );
@ -105,8 +105,8 @@ public class EntityRepresentationStrategyMap implements EntityRepresentationStra
public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) {
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess(
null,
bootAttributeDescriptor.getName()
);
bootAttributeDescriptor.getName(),
true );
}
@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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,15 +34,24 @@ public class PropertyAccessBasicImpl implements PropertyAccess {
public PropertyAccessBasicImpl(
PropertyAccessStrategyBasicImpl strategy,
Class containerJavaType,
final String propertyName) {
Class<?> containerJavaType,
final String propertyName,
boolean setterRequired) {
this.strategy = strategy;
final Method getterMethod = ReflectHelper.findGetterMethod( containerJavaType, propertyName );
this.getter = new GetterMethodImpl( containerJavaType, propertyName, getterMethod );
final Method setterMethod = ReflectHelper.findSetterMethod( containerJavaType, propertyName, getterMethod.getReturnType() );
this.setter = new SetterMethodImpl( containerJavaType, propertyName, setterMethod );
final Method 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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@ public class PropertyAccessStrategyEnhancedImpl implements PropertyAccessStrateg
public static final PropertyAccessStrategyEnhancedImpl INSTANCE = new PropertyAccessStrategyEnhancedImpl();
@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 );
}
}

View File

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

View File

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

View File

@ -21,7 +21,7 @@ public class PropertyAccessStrategyMapImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyMapImpl INSTANCE = new PropertyAccessStrategyMapImpl();
@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.
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();
@Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) {
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return new PropertyAccessMixedImpl( this, containerJavaType, propertyName );
}
}

View File

@ -31,7 +31,7 @@ public class PropertyAccessStrategyNoopImpl implements PropertyAccessStrategy {
public static final PropertyAccessStrategyNoopImpl INSTANCE = new PropertyAccessStrategyNoopImpl();
@Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) {
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
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).
* Acts as a factory for {@link PropertyAccess} instances.
*
* @author Steve Ebersole
* Acts as a factory for {@link PropertyAccess} instances.
*/
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 propertyName The property name
* @param setterRequired Whether it is an error if we are unable to find a corresponding setter
*
* @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.lang.reflect.Method;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
* 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 {
final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess(
clazz,
paramName
);
paramName,
true );
final Getter getter = propertyAccess.getGetter();
final Class<?> retType = getter.getReturnTypeClass();
final Object object = getter.get( bean );

View File

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

View File

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

View File

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

View File

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

View File

@ -38,10 +38,10 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
private PropertyAccess buildPropertyAccess(Property mappedProperty) {
if ( mappedProperty.isBackRef() ) {
return mappedProperty.getPropertyAccessStrategy( null ).buildPropertyAccess( null, mappedProperty.getName() );
return mappedProperty.getPropertyAccessStrategy( null ).buildPropertyAccess( null, mappedProperty.getName(), true );
}
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 {
@Override
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) {
return super.buildPropertyAccess( containerJavaType, propertyName );
public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName, boolean setterRequired) {
return super.buildPropertyAccess( containerJavaType, propertyName, setterRequired );
}
}
}

View File

@ -28,49 +28,49 @@ public class BeanReflectionHelper {
static {
final PropertyAccessStrategyBasicImpl propertyAccessStrategy = new PropertyAccessStrategyBasicImpl();
PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someString" );
PropertyAccess propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someString", true );
Getter getter = propertyAccess.getGetter();
Setter setter = propertyAccess.getSetter();
getterNames[0] = getter.getMethodName();
types[0] = getter.getReturnTypeClass();
setterNames[0] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
getterNames[1] = getter.getMethodName();
types[1] = getter.getReturnTypeClass();
setterNames[1] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
getterNames[2] = getter.getMethodName();
types[2] = getter.getReturnTypeClass();
setterNames[2] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
getterNames[3] = getter.getMethodName();
types[3] = getter.getReturnTypeClass();
setterNames[3] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
getterNames[4] = getter.getMethodName();
types[4] = getter.getReturnTypeClass();
setterNames[4] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
getterNames[5] = getter.getMethodName();
types[5] = getter.getReturnTypeClass();
setterNames[5] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject" );
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject", true );
getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter();
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.Component;
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.DomainModelScope;
@ -31,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@JiraKey( "HHH-14950" )
public class InstantiationTests {
@Test
public void modelTest(DomainModelScope scope) {
public void bootModelTest(DomainModelScope scope) {
scope.withHierarchy( Person.class, (personMapping) -> {
final Property name = personMapping.getProperty( "name" );
final Component nameMapping = (Component) name.getValue();
@ -44,7 +51,23 @@ public class InstantiationTests {
}
@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) {
scope.inTransaction( (session) -> {
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.Component;
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.DomainModelScope;
@ -34,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@JiraKey( "HHH-14950" )
public class InstantiationTests {
@Test
public void modelTest(DomainModelScope scope) {
public void bootModelTest(DomainModelScope scope) {
scope.withHierarchy( Person.class, (personMapping) -> {
final Property name = personMapping.getProperty( "name" );
final Component nameMapping = (Component) name.getValue();
@ -47,7 +54,23 @@ public class InstantiationTests {
}
@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) {
scope.inTransaction( (session) -> {
final Person mick = new Person( 1, Name.make( "Mick", "Jagger" ) );

View File

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

View File

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

View File

@ -73,13 +73,13 @@ public class BasicPropertyAccessorTest extends BaseUnitTestCase {
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( 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.getSetter().getMethod().getParameterTypes()[0] );
}

View File

@ -36,7 +36,7 @@ public class PropertyAccessStrategyMapTest extends BaseUnitTestCase {
final PropertyAccessStrategyMapImpl accessStrategy = PropertyAccessStrategyMapImpl.INSTANCE;
try {
accessStrategy.buildPropertyAccess( Date.class, "time" );
accessStrategy.buildPropertyAccess( Date.class, "time", true );
fail("Should throw IllegalArgumentException");
}
@ -54,7 +54,7 @@ public class PropertyAccessStrategyMapTest extends BaseUnitTestCase {
final String value = "testValue";
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<>();

View File

@ -54,7 +54,7 @@ logger.tooling-schema-script-graph.appenderRef.subsystem.ref=subsystem
# Logging related to the creation of DomainResult/Fetch graphs
logger.sql-result-graph.name=org.hibernate.orm.sql.results
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
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 );
Getter value = GETTER_CACHE.get( key );
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
GETTER_CACHE.put( key, value );
}
@ -70,7 +70,7 @@ public abstract class ReflectionTools {
final Pair<Class, String> key = Pair.make( cls, propertyName );
Setter value = SETTER_CACHE.get( key );
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
SETTER_CACHE.put( key, value );
}

View File

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