Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public ReflectionOptimizer getReflectionOptimizer(
final Method[] getters = new Method[getterNames.length];
final Method[] setters = new Method[setterNames.length];
try {
findAccessors( clazz, getterNames, setterNames, types, getters, setters );
unwrapPropertyInfos( clazz, getterNames, setterNames, types, getters, setters );
}
catch (InvalidPropertyAccessorException ex) {
LOG.unableToGenerateReflectionOptimizer( clazz.getName(), ex.getMessage() );
Expand Down Expand Up @@ -179,6 +179,18 @@ public ReflectionOptimizer getReflectionOptimizer(

@Override
public @Nullable ReflectionOptimizer getReflectionOptimizer(Class<?> clazz, Map<String, PropertyAccess> propertyAccessMap) {
final PropertyInfo[] propertyInfos = new PropertyInfo[propertyAccessMap.size()];
int i = 0;
for ( Map.Entry<String, PropertyAccess> entry : propertyAccessMap.entrySet() ) {
final String propertyName = entry.getKey();
final PropertyAccess propertyAccess = entry.getValue();
propertyInfos[i++] = new PropertyInfo( propertyName, propertyAccess );
}
return getReflectionOptimizer( clazz, propertyInfos );
}

@Override
public @Nullable ReflectionOptimizer getReflectionOptimizer(Class<?> clazz, PropertyInfo[] propertyInfos) {
final Class<?> fastClass;
if ( !clazz.isInterface() && !Modifier.isAbstract( clazz.getModifiers() ) ) {
// we only provide a fast class instantiator if the class can be instantiated
Expand All @@ -203,17 +215,17 @@ public ReflectionOptimizer getReflectionOptimizer(
fastClass = null;
}

final Member[] getters = new Member[propertyAccessMap.size()];
final Member[] setters = new Member[propertyAccessMap.size()];
final Member[] getters = new Member[propertyInfos.length];
final Member[] setters = new Member[propertyInfos.length];
final String[] propertyNames = new String[propertyInfos.length];
try {
findAccessors( clazz, propertyAccessMap, getters, setters );
unwrapPropertyInfos( clazz, propertyInfos, propertyNames, getters, setters );
}
catch (InvalidPropertyAccessorException ex) {
LOG.unableToGenerateReflectionOptimizer( clazz.getName(), ex.getMessage() );
return null;
}

final String[] propertyNames = propertyAccessMap.keySet().toArray( new String[0] );
final Class<?> superClass = determineAccessOptimizerSuperClass( clazz, propertyNames, getters, setters );

final String className = clazz.getName() + "$" + OPTIMIZER_PROXY_NAMING_SUFFIX + NameEncodeHelper.encodeName( propertyNames, getters, setters );
Expand Down Expand Up @@ -391,7 +403,7 @@ public ByteBuddyProxyHelper getByteBuddyProxyHelper() {
return byteBuddyProxyHelper;
}

private static void findAccessors(
private static void unwrapPropertyInfos(
Class<?> clazz,
String[] getterNames,
String[] setterNames,
Expand Down Expand Up @@ -432,14 +444,17 @@ else if ( Modifier.isPrivate( setters[i].getModifiers() ) ) {
}
}

private static void findAccessors(
private static void unwrapPropertyInfos(
Class<?> clazz,
Map<String, PropertyAccess> propertyAccessMap,
PropertyInfo[] propertyInfos,
String[] propertyNames,
Member[] getters,
Member[] setters) {
int i = 0;
for ( Map.Entry<String, PropertyAccess> entry : propertyAccessMap.entrySet() ) {
final PropertyAccess propertyAccess = entry.getValue();
for ( PropertyInfo propertyInfo : propertyInfos ) {
final String propertyName = propertyInfo.propertyName();
final PropertyAccess propertyAccess = propertyInfo.propertyAccess();
propertyNames[i] = propertyName;
if ( propertyAccess instanceof PropertyAccessEmbeddedImpl ) {
getters[i] = EMBEDDED_MEMBER;
setters[i] = EMBEDDED_MEMBER;
Expand All @@ -448,14 +463,14 @@ private static void findAccessors(
}
final Getter getter = propertyAccess.getGetter();
if ( getter == null ) {
throw new InvalidPropertyAccessorException( "invalid getter for property [" + entry.getKey() + "]" );
throw new InvalidPropertyAccessorException( "invalid getter for property [" + propertyName + "]" );
}
final Setter setter = propertyAccess.getSetter();
if ( setter == null ) {
throw new InvalidPropertyAccessorException(
String.format(
"cannot find a setter for [%s] on type [%s]",
entry.getKey(),
propertyName,
clazz.getName()
)
);
Expand All @@ -471,7 +486,7 @@ else if ( getter instanceof GetterFieldImpl getterField ) {
throw new InvalidPropertyAccessorException(
String.format(
"cannot find a getter for [%s] on type [%s]",
entry.getKey(),
propertyName,
clazz.getName()
)
);
Expand All @@ -490,7 +505,7 @@ else if ( setter instanceof SetterFieldImpl setterField ) {
throw new InvalidPropertyAccessorException(
String.format(
"cannot find a setter for [%s] on type [%s]",
entry.getKey(),
propertyName,
clazz.getName()
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
package org.hibernate.bytecode.spi;

import java.util.HashMap;
import java.util.Map;

import org.hibernate.bytecode.enhance.spi.EnhancementContext;
Expand Down Expand Up @@ -55,9 +56,35 @@ public interface BytecodeProvider extends Service {
* @param clazz The class to be reflected upon.
* @param propertyAccessMap The ordered property access map
* @return The reflection optimization delegate.
* @deprecated Use {@link #getReflectionOptimizer(Class, PropertyInfo[])} instead
*/
@Deprecated(forRemoval = true)
@Nullable ReflectionOptimizer getReflectionOptimizer(Class<?> clazz, Map<String, PropertyAccess> propertyAccessMap);

/**
* Retrieve the ReflectionOptimizer delegate for this provider
* capable of generating reflection optimization components.
*
* @param clazz The class to be reflected upon.
* @param propertyInfos The ordered property infos
* @return The reflection optimization delegate.
*/
default @Nullable ReflectionOptimizer getReflectionOptimizer(Class<?> clazz, PropertyInfo[] propertyInfos) {
final Map<String, PropertyAccess> map = new HashMap<>();
for ( int i = 0; i < propertyInfos.length; i++ ) {
map.put( propertyInfos[i].propertyName(), propertyInfos[i].propertyAccess() );
}
return getReflectionOptimizer( clazz, map );
}

/**
* Information about a property of a class, needed for generating reflection optimizers.
*
* @param propertyName The name of the property
* @param propertyAccess The property access
*/
record PropertyInfo(String propertyName, PropertyAccess propertyAccess) {}

/**
* Returns a byte code enhancer that implements the enhancements described in the supplied enhancement context.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
Expand Down Expand Up @@ -197,15 +197,15 @@ private static ReflectionOptimizer buildReflectionOptimizer(
&& bootDescriptor.getCustomInstantiator() == null
&& bootDescriptor.getInstantiator() == null
&& !bootDescriptor.isPolymorphic() ) {
final Map<String, PropertyAccess> propertyAccessMap = new LinkedHashMap<>();
int i = 0;
for ( Property property : bootDescriptor.getProperties() ) {
propertyAccessMap.put( property.getName(), propertyAccesses[i] );
i++;
final List<Property> properties = bootDescriptor.getProperties();
final BytecodeProvider.PropertyInfo[] propertyInfos = new BytecodeProvider.PropertyInfo[properties.size()];
for ( int i = 0; i < properties.size(); i++ ) {
final Property property = properties.get( i );
propertyInfos[i] = new BytecodeProvider.PropertyInfo( property.getName(), propertyAccesses[i] );
}
return creationContext.getServiceRegistry()
.requireService( BytecodeProvider.class )
.getReflectionOptimizer( bootDescriptor.getComponentClass(), propertyAccessMap );
.getReflectionOptimizer( bootDescriptor.getComponentClass(), propertyInfos );
}
else {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
package org.hibernate.metamodel.internal;

import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -59,6 +60,7 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent

private final String identifierPropertyName;
private final PropertyAccess identifierPropertyAccess;
private final BytecodeProvider.PropertyInfo[] propertyInfos;
private final Map<String, PropertyAccess> propertyAccessMap;
private final EmbeddableRepresentationStrategyPojo mapsIdRepresentationStrategy;

Expand Down Expand Up @@ -119,7 +121,8 @@ public EntityRepresentationStrategyPojoStandard(
creationContext
);

propertyAccessMap = buildPropertyAccessMap( bootDescriptor );
propertyInfos = buildPropertyInfos( bootDescriptor );
propertyAccessMap = buildPropertyAccessMap( propertyInfos );
reflectionOptimizer = resolveReflectionOptimizer( bytecodeProvider );

instantiator = determineInstantiator( bootDescriptor, runtimeDescriptor.getEntityMetamodel() );
Expand Down Expand Up @@ -155,12 +158,22 @@ private ProxyFactory resolveProxyFactory(
}
}

private Map<String, PropertyAccess> buildPropertyAccessMap(PersistentClass bootDescriptor) {
final Map<String, PropertyAccess> propertyAccessMap = new LinkedHashMap<>();
for ( Property property : bootDescriptor.getPropertyClosure() ) {
propertyAccessMap.put( property.getName(), makePropertyAccess( property ) );
private Map<String, PropertyAccess> buildPropertyAccessMap(BytecodeProvider.PropertyInfo[] propertyInfos) {
final Map<String, PropertyAccess> map = new HashMap<>( propertyInfos.length );
for ( BytecodeProvider.PropertyInfo propertyInfo : propertyInfos ) {
map.put( propertyInfo.propertyName(), propertyInfo.propertyAccess() );
}
return propertyAccessMap;
return map;
}

private BytecodeProvider.PropertyInfo[] buildPropertyInfos(PersistentClass bootDescriptor) {
final List<Property> properties = bootDescriptor.getPropertyClosure();
final BytecodeProvider.PropertyInfo[] propertyInfos = new BytecodeProvider.PropertyInfo[properties.size()];
for ( int i = 0; i < properties.size(); i++ ) {
final Property property = properties.get( i );
propertyInfos[i] = new BytecodeProvider.PropertyInfo( property.getName(), makePropertyAccess( property ) );
}
return propertyInfos;
}

private EntityInstantiator determineInstantiator(PersistentClass bootDescriptor, EntityMetamodel entityMetamodel) {
Expand Down Expand Up @@ -303,11 +316,11 @@ private static ProxyFactory instantiateProxyFactory(
}

private ReflectionOptimizer resolveReflectionOptimizer(BytecodeProvider bytecodeProvider) {
return bytecodeProvider.getReflectionOptimizer( mappedJtd.getJavaTypeClass(), propertyAccessMap );
return bytecodeProvider.getReflectionOptimizer( mappedJtd.getJavaTypeClass(), propertyInfos );
}

private PropertyAccess makePropertyAccess(Property bootAttributeDescriptor) {
final Class<?> mappedClass = mappedJtd.getJavaTypeClass();
final Class<?> mappedClass = bootAttributeDescriptor.getPersistentClass().getMappedClass();
final String descriptorName = bootAttributeDescriptor.getName();
final var strategy = propertyAccessStrategy( bootAttributeDescriptor, mappedClass, strategySelector );
if ( strategy == null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4822,26 +4822,27 @@ private void inheritSupertypeSpecialAttributeMappings() {
final NonIdentifierAttribute[] properties = entityMetamodel.getProperties();
final AttributeMappingsMap.Builder mappingsBuilder = AttributeMappingsMap.builder();
int fetchableIndex = getFetchableIndexOffset();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
final NonIdentifierAttribute runtimeAttributeDefinition = properties[i];
final String attributeName = runtimeAttributeDefinition.getName();
final Property bootProperty = bootEntityDescriptor.getProperty( attributeName );
if ( superMappingType == null
|| superMappingType.findAttributeMapping( bootProperty.getName() ) == null ) {
mappingsBuilder.put(
attributeName,
generateNonIdAttributeMapping(
runtimeAttributeDefinition,
bootProperty,
stateArrayPosition++,
fetchableIndex++,
creationProcess
)
);
}
declaredAttributeMappings = mappingsBuilder.build();
// otherwise, it's defined on the supertype, skip it here
// For every property that is "owned" by this persistent class, create a declared attribute mapping
final List<Property> bootProperties = bootEntityDescriptor.getProperties();
// EntityMetamodel uses getPropertyClosure(), which includes the properties of the super type,
// so use that property span as offset when indexing into the EntityMetamodel NonIdentifierAttribute[]
final int superclassPropertiesOffset = superMappingType == null ? 0
: superMappingType.getEntityPersister().getEntityMetamodel().getPropertySpan();
for ( int i = 0; i < bootProperties.size(); i++ ) {
final Property bootProperty = bootProperties.get( i );
assert properties[superclassPropertiesOffset + i].getName().equals( bootProperty.getName() );
mappingsBuilder.put(
bootProperty.getName(),
generateNonIdAttributeMapping(
properties[superclassPropertiesOffset + i],
bootProperty,
stateArrayPosition++,
fetchableIndex++,
creationProcess
)
);
}
declaredAttributeMappings = mappingsBuilder.build();
}

private static BeforeExecutionGenerator createVersionGenerator
Expand Down
Loading
Loading