HHH-15493 Allow Java records as @IdClass

This commit is contained in:
Marco Belladelli 2024-02-19 13:45:54 +01:00 committed by Christian Beikov
parent efb02b72e5
commit 1196f72798
3 changed files with 42 additions and 12 deletions

View File

@ -441,8 +441,7 @@ public class EmbeddableBinder {
addElementsOfClass( classElements, container, context);
//add elements of the embeddable's mapped superclasses
XClass superClass = annotatedClass.getSuperclass();
while ( superClass != null && ( superClass.isAnnotationPresent( MappedSuperclass.class )
|| ( isIdClass && !Object.class.getName().equals( superClass.getName() ) ) ) ) {
while ( isValidSuperclass( superClass, isIdClass ) ) {
//FIXME: proper support of type variables incl var resolved at upper levels
final PropertyContainer superContainer =
new PropertyContainer( superClass, annotatedClass, propertyAccessor );
@ -452,6 +451,17 @@ public class EmbeddableBinder {
return classElements;
}
private static boolean isValidSuperclass(XClass superClass, boolean isIdClass) {
if ( superClass == null ) {
return false;
}
return superClass.isAnnotationPresent( MappedSuperclass.class )
|| ( isIdClass
&& !superClass.getName().equals( Object.class.getName() )
&& !superClass.getName().equals( "java.lang.Record" ) );
}
private static List<PropertyData> collectBaseClassElements(
PropertyData baseInferredData,
AccessType propertyAccessor,

View File

@ -6,16 +6,22 @@
*/
package org.hibernate.metamodel.mapping.internal;
import java.util.Locale;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.internal.EmbeddableInstantiatorPojoStandard;
import org.hibernate.metamodel.internal.EmbeddableInstantiatorRecordStandard;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.type.descriptor.java.JavaType;
import static org.hibernate.internal.util.ReflectHelper.isRecord;
/**
* EmbeddableRepresentationStrategy for an IdClass mapping
*/
@ -25,7 +31,9 @@ public class IdClassRepresentationStrategy implements EmbeddableRepresentationSt
public IdClassRepresentationStrategy(IdClassEmbeddable idClassEmbeddable) {
this.idClassType = idClassEmbeddable.getMappedJavaType();
this.instantiator = new EmbeddableInstantiatorPojoStandard( idClassType, () -> idClassEmbeddable );
this.instantiator = isRecord( idClassType.getJavaTypeClass() ) ?
new EmbeddableInstantiatorRecordStandard( idClassType.getJavaTypeClass() ) :
new EmbeddableInstantiatorPojoStandard( idClassType, () -> idClassEmbeddable );
}
@Override
@ -50,9 +58,23 @@ public class IdClassRepresentationStrategy implements EmbeddableRepresentationSt
@Override
public PropertyAccess resolvePropertyAccess(Property bootAttributeDescriptor) {
return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess(
final PropertyAccessStrategy strategy = bootAttributeDescriptor.getPropertyAccessStrategy( idClassType.getJavaTypeClass() );
if ( strategy == null ) {
throw new HibernateException(
String.format(
Locale.ROOT,
"Could not resolve PropertyAccess for attribute `%s#%s`",
idClassType.getTypeName(),
bootAttributeDescriptor.getName()
)
);
}
return strategy.buildPropertyAccess(
idClassType.getJavaTypeClass(),
bootAttributeDescriptor.getName(),
true );
false
);
}
}

View File

@ -231,10 +231,6 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
}
final Object id = identifierValueMapper.getRepresentationStrategy().getInstantiator().instantiate(
null,
sessionFactory
);
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
for ( int i = 0; i < propertyValues.length; i++ ) {
@ -268,8 +264,10 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
propertyValues[i] = o;
}
}
identifierValueMapper.setValues( id, propertyValues );
return id;
return identifierValueMapper.getRepresentationStrategy().getInstantiator().instantiate(
() -> propertyValues,
sessionFactory
);
}
else {
return entity;