Skip to content

Commit

Permalink
Revert "HHH-15072 Add out of the box support for records as embeddables"
Browse files Browse the repository at this point in the history
This reverts commit 75240b0.
  • Loading branch information
beikov committed Sep 2, 2022
1 parent 1d37e52 commit a801525
Show file tree
Hide file tree
Showing 9 changed files with 17 additions and 361 deletions.
10 changes: 1 addition & 9 deletions hibernate-core/src/main/java/org/hibernate/cfg/AccessType.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ public enum AccessType {
/**
* Access to value via field
*/
FIELD( "field" ),

/**
* Access to value via record component accessor
*/
RECORD( "record" );
FIELD( "field" );

private final String accessType;

Expand Down Expand Up @@ -64,9 +59,6 @@ else if ( FIELD.getType().equals( externalName ) ) {
else if ( PROPERTY.getType().equals( externalName ) ) {
return PROPERTY;
}
else if ( RECORD.getType().equals( externalName ) ) {
return RECORD;
}
else {
// TODO historically if the externalName string could not be matched default access was used. Maybe this should be an exception though!?
return DEFAULT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,6 @@ private AccessType determineDefaultAccessType() {
return AccessType.FIELD;
}
}
for ( XProperty prop : xclass.getDeclaredProperties( AccessType.RECORD.getType() ) ) {
final boolean isEmbeddedId = prop.isAnnotationPresent( EmbeddedId.class );
if ( prop.isAnnotationPresent( Id.class ) || isEmbeddedId ) {
return AccessType.RECORD;
}
}
}
}
throw new AnnotationException( "No identifier specified for entity: " + clazz );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
package org.hibernate.cfg;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
Expand All @@ -24,7 +25,6 @@
import org.hibernate.annotations.Target;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.cfg.annotations.HCANNHelper;
Expand Down Expand Up @@ -85,51 +85,36 @@ class PropertyContainer {
this.classLevelAccessType = localClassLevelAccessType != AccessType.DEFAULT
? localClassLevelAccessType
: defaultClassLevelAccessType;
assert classLevelAccessType == AccessType.FIELD || classLevelAccessType == AccessType.PROPERTY
|| classLevelAccessType == AccessType.RECORD;
assert classLevelAccessType == AccessType.FIELD || classLevelAccessType == AccessType.PROPERTY;


final List<XProperty> fields = xClass.getDeclaredProperties( AccessType.FIELD.getType() );
final List<XProperty> getters = xClass.getDeclaredProperties( AccessType.PROPERTY.getType() );
final List<XProperty> recordComponents = xClass.getDeclaredProperties( AccessType.RECORD.getType() );

preFilter( fields, getters, recordComponents );
preFilter( fields, getters );

final Map<String,XProperty> persistentAttributesFromGetters = new HashMap<>();
final Map<String,XProperty> persistentAttributesFromComponents = new HashMap<>();

final Map<String, XProperty> localAttributeMap;
// If the record class has only record components which match up with fields and no additional getters,
// we can retain the property order, to match up with the record component order
if ( !recordComponents.isEmpty() && recordComponents.size() == fields.size() && getters.isEmpty() ) {
localAttributeMap = new LinkedHashMap<>();
}
else {
localAttributeMap = new TreeMap<>();
}
final TreeMap<String, XProperty> localAttributeMap = new TreeMap<>();
collectPersistentAttributesUsingLocalAccessType(
xClass,
localAttributeMap,
persistentAttributesFromGetters,
persistentAttributesFromComponents,
fields,
getters,
recordComponents
getters
);
collectPersistentAttributesUsingClassLevelAccessType(
xClass,
classLevelAccessType,
localAttributeMap,
persistentAttributesFromGetters,
persistentAttributesFromComponents,
fields,
getters,
recordComponents
getters
);
this.persistentAttributes = verifyAndInitializePersistentAttributes( xClass, localAttributeMap );
}

private void preFilter(List<XProperty> fields, List<XProperty> getters, List<XProperty> recordComponents) {
private void preFilter(List<XProperty> fields, List<XProperty> getters) {
Iterator<XProperty> propertyIterator = fields.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty property = propertyIterator.next();
Expand All @@ -145,24 +130,14 @@ private void preFilter(List<XProperty> fields, List<XProperty> getters, List<XPr
propertyIterator.remove();
}
}

propertyIterator = recordComponents.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty property = propertyIterator.next();
if ( mustBeSkipped( property ) ) {
propertyIterator.remove();
}
}
}

private static void collectPersistentAttributesUsingLocalAccessType(
XClass xClass,
Map<String, XProperty> persistentAttributeMap,
TreeMap<String, XProperty> persistentAttributeMap,
Map<String,XProperty> persistentAttributesFromGetters,
Map<String,XProperty> persistentAttributesFromComponents,
List<XProperty> fields,
List<XProperty> getters,
List<XProperty> recordComponents) {
List<XProperty> getters) {

// Check fields...
Iterator<XProperty> propertyIterator = fields.iterator();
Expand Down Expand Up @@ -208,40 +183,22 @@ private static void collectPersistentAttributesUsingLocalAccessType(
persistentAttributeMap.put( name, xProperty );
persistentAttributesFromGetters.put( name, xProperty );
}

// Check record components...
propertyIterator = recordComponents.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty xProperty = propertyIterator.next();
final Access localAccessAnnotation = xProperty.getAnnotation( Access.class );
if ( localAccessAnnotation == null ) {
continue;
}

propertyIterator.remove();
final String name = xProperty.getName();
persistentAttributeMap.put( name, xProperty );
persistentAttributesFromComponents.put( name, xProperty );
}
}

private static void collectPersistentAttributesUsingClassLevelAccessType(
XClass xClass,
AccessType classLevelAccessType,
Map<String, XProperty> persistentAttributeMap,
TreeMap<String, XProperty> persistentAttributeMap,
Map<String,XProperty> persistentAttributesFromGetters,
Map<String,XProperty> persistentAttributesFromComponents,
List<XProperty> fields,
List<XProperty> getters,
List<XProperty> recordComponents) {
List<XProperty> getters) {
if ( classLevelAccessType == AccessType.FIELD ) {
for ( XProperty field : fields ) {
final String name = field.getName();
if ( persistentAttributeMap.containsKey( name ) ) {
if ( persistentAttributeMap.containsKey( field.getName() ) ) {
continue;
}

persistentAttributeMap.put( name, field );
persistentAttributeMap.put( field.getName(), field );
}
}
else {
Expand All @@ -251,7 +208,7 @@ private static void collectPersistentAttributesUsingClassLevelAccessType(
// HHH-10242 detect registration of the same property getter twice - eg boolean isId() + UUID getId()
final XProperty previous = persistentAttributesFromGetters.get( name );
if ( previous != null ) {
throw new MappingException(
throw new org.hibernate.boot.MappingException(
LOG.ambiguousPropertyMethods(
xClass.getName(),
HCANNHelper.annotatedElementSignature( previous ),
Expand All @@ -268,18 +225,6 @@ private static void collectPersistentAttributesUsingClassLevelAccessType(
persistentAttributeMap.put( getter.getName(), getter );
persistentAttributesFromGetters.put( name, getter );
}
// When a user uses the `property` access strategy for the entity owning an embeddable,
// we also have to add the attributes for record components,
// because record classes usually don't have getters, but just the record component accessors
for ( XProperty recordComponent : recordComponents ) {
final String name = recordComponent.getName();
if ( persistentAttributeMap.containsKey( name ) ) {
continue;
}

persistentAttributeMap.put( name, recordComponent );
persistentAttributesFromComponents.put( name, recordComponent );
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ public final class ReflectHelper {

private static final Method OBJECT_EQUALS;
private static final Method OBJECT_HASHCODE;
private static final Class<?> RECORD_CLASS;
private static final Method GET_RECORD_COMPONENTS;
private static final Method GET_NAME;
private static final Method GET_TYPE;

static {
Method eq;
Expand All @@ -68,25 +64,6 @@ public final class ReflectHelper {
}
OBJECT_EQUALS = eq;
OBJECT_HASHCODE = hash;

Class<?> recordClass = null;
Method getRecordComponents = null;
Method getName = null;
Method getType = null;
try {
recordClass = Class.forName( "java.lang.Record" );
getRecordComponents = Class.class.getMethod( "getRecordComponents" );
final Class<?> recordComponentClass = Class.forName( "java.lang.reflect.RecordComponent" );
getName = recordComponentClass.getMethod( "getName" );
getType = recordComponentClass.getMethod( "getType" );
}
catch (Exception e) {
// Ignore
}
RECORD_CLASS = recordClass;
GET_RECORD_COMPONENTS = getRecordComponents;
GET_NAME = getName;
GET_TYPE = getType;
}

/**
Expand Down Expand Up @@ -460,15 +437,6 @@ public static Method findGetterMethod(Class containerClass, String propertyName)
Class checkClass = containerClass;
Method getter = null;

if ( isRecord( containerClass ) ) {
try {
getter = containerClass.getMethod( propertyName, NO_PARAM_SIGNATURE );
}
catch (NoSuchMethodException e) {
// Ignore
}
}

// check containerClass, and then its super types (if any)
while ( getter == null && checkClass != null ) {
if ( checkClass.equals( Object.class ) ) {
Expand Down Expand Up @@ -516,14 +484,6 @@ private static Method getGetterOrNull(Class[] interfaces, String propertyName) {
}

private static Method getGetterOrNull(Class containerClass, String propertyName) {
if ( isRecord( containerClass ) ) {
try {
return containerClass.getMethod( propertyName, NO_PARAM_SIGNATURE );
}
catch (NoSuchMethodException e) {
// Ignore
}
}
for ( Method method : containerClass.getDeclaredMethods() ) {
// if the method has parameters, skip it
if ( method.getParameterCount() != 0 ) {
Expand Down Expand Up @@ -753,56 +713,10 @@ public static Method findGetterMethodForFieldAccess(Field field, String property
}
}
}
if ( isRecord( field.getDeclaringClass() ) ) {
try {
return field.getDeclaringClass().getMethod( field.getName(), NO_PARAM_SIGNATURE );
}
catch (NoSuchMethodException e) {
// Ignore
}
}

return null;
}

public static boolean isRecord(Class<?> declaringClass) {
return RECORD_CLASS != null && RECORD_CLASS.isAssignableFrom( declaringClass );
}

public static Class<?>[] getRecordComponentTypes(Class<?> javaType) {
try {
final Object[] recordComponents = (Object[]) GET_RECORD_COMPONENTS.invoke( javaType );
final Class<?>[] componentTypes = new Class[recordComponents.length];
for (int i = 0; i < recordComponents.length; i++ ) {
componentTypes[i] = (Class<?>) GET_TYPE.invoke( recordComponents[i] );
}
return componentTypes;
}
catch (Exception e) {
throw new IllegalArgumentException(
"Could not determine the record components for: " + javaType.getName(),
e
);
}
}

public static String[] getRecordComponentNames(Class<?> javaType) {
try {
final Object[] recordComponents = (Object[]) GET_RECORD_COMPONENTS.invoke( javaType );
final String[] componentNames = new String[recordComponents.length];
for (int i = 0; i < recordComponents.length; i++ ) {
componentNames[i] = (String) GET_NAME.invoke( recordComponents[i] );
}
return componentNames;
}
catch (Exception e) {
throw new IllegalArgumentException(
"Could not determine the record components for: " + javaType.getName(),
e
);
}
}

public static <T> Class<T> getClass(java.lang.reflect.Type type) {
if ( type == null ) {
return null;
Expand Down
24 changes: 0 additions & 24 deletions hibernate-core/src/main/java/org/hibernate/mapping/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
Expand Down Expand Up @@ -569,10 +568,6 @@ private int[] sortProperties(boolean forceRetainOriginalOrder) {
if ( originalPropertyOrder != ArrayHelper.EMPTY_INT_ARRAY ) {
return originalPropertyOrder;
}
// Don't sort the properties for a simple record
if ( isSimpleRecord() ) {
return this.originalPropertyOrder = null;
}
final int[] originalPropertyOrder;
// We need to capture the original property order if this is an alternate unique key or embedded component property
// to be able to sort the other side of the foreign key accordingly
Expand Down Expand Up @@ -609,25 +604,6 @@ private int[] sortProperties(boolean forceRetainOriginalOrder) {
return this.originalPropertyOrder = originalPropertyOrder;
}

private boolean isSimpleRecord() {
// A simple record is given, when the properties match the order of the record component names
final Class<?> componentClass = resolveComponentClass();
if ( componentClass == null || !ReflectHelper.isRecord( componentClass ) ) {
return false;
}
final String[] recordComponentNames = ReflectHelper.getRecordComponentNames( componentClass );
if ( recordComponentNames.length != properties.size() ) {
return false;
}
for ( int i = 0; i < recordComponentNames.length; i++ ) {
if ( !recordComponentNames[i].equals( properties.get( i ).getName() ) ) {
return false;
}
}

return true;
}

public Class<? extends EmbeddableInstantiator> getCustomInstantiator() {
return customInstantiator;
}
Expand Down

0 comments on commit a801525

Please sign in to comment.