HHH-15090 Fix access to public field with extended bytecode enhancement returning null for entity lazy-loaded from polymorphic toOne association

This commit is contained in:
Yoann Rodière 2022-02-24 17:44:21 +01:00
parent 2ea04dc524
commit 223856cfd0
2 changed files with 17 additions and 11 deletions

View File

@ -24,6 +24,7 @@ import java.security.PrivilegedAction;
import java.util.function.Function;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.proxy.ProxyConfiguration;
@ -248,7 +249,7 @@ public final class ByteBuddyState {
private final ElementMatcher<? super MethodDescription> groovyGetMetaClassFilter;
private final ElementMatcher<? super MethodDescription> virtualNotFinalizerFilter;
private final ElementMatcher<? super MethodDescription> hibernateGeneratedMethodFilter;
private final ElementMatcher<? super MethodDescription> proxyNonInterceptedMethodFilter;
private final MethodDelegation delegateToInterceptorDispatcherMethodDelegation;
private final FieldAccessor.PropertyConfigurable interceptorFieldAccessor;
@ -256,7 +257,11 @@ public final class ByteBuddyState {
this.groovyGetMetaClassFilter = isSynthetic().and( named( "getMetaClass" )
.and( returns( td -> "groovy.lang.MetaClass".equals( td.getName() ) ) ) );
this.virtualNotFinalizerFilter = isVirtual().and( not( isFinalizer() ) );
this.hibernateGeneratedMethodFilter = nameStartsWith( "$$_hibernate_" ).and( isVirtual() );
this.proxyNonInterceptedMethodFilter = nameStartsWith( "$$_hibernate_" ).and( isVirtual() )
// HHH-15090: Don't apply extended enhancement reader/writer methods to the proxy;
// those need to be executed on the actual entity.
.and( not( nameStartsWith( EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX ) ) )
.and( not( nameStartsWith( EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX ) ) );
PrivilegedAction<MethodDelegation> delegateToInterceptorDispatcherMethodDelegationPrivilegedAction =
new PrivilegedAction<MethodDelegation>() {
@ -294,8 +299,8 @@ public final class ByteBuddyState {
return virtualNotFinalizerFilter;
}
public ElementMatcher<? super MethodDescription> getHibernateGeneratedMethodFilter() {
return hibernateGeneratedMethodFilter;
public ElementMatcher<? super MethodDescription> getProxyNonInterceptedMethodFilter() {
return proxyNonInterceptedMethodFilter;
}
public MethodDelegation getDelegateToInterceptorDispatcherMethodDelegation() {

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.proxy.pojo.bytebuddy;
import static org.hibernate.internal.CoreLogging.messageLogger;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@ -31,8 +33,6 @@ import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.SuperMethodCall;
import static org.hibernate.internal.CoreLogging.messageLogger;
public class ByteBuddyProxyHelper implements Serializable {
private static final CoreMessageLogger LOG = messageLogger( ByteBuddyProxyHelper.class );
@ -64,18 +64,19 @@ public class ByteBuddyProxyHelper implements Serializable {
}
private Function<ByteBuddy, DynamicType.Builder<?>> proxyBuilder(Class persistentClass, Class[] interfaces) {
ByteBuddyState.ProxyDefinitionHelpers helpers = byteBuddyState.getProxyDefinitionHelpers();
return byteBuddy -> byteBuddy
.ignore( byteBuddyState.getProxyDefinitionHelpers().getGroovyGetMetaClassFilter() )
.ignore( helpers.getGroovyGetMetaClassFilter() )
.with( new NamingStrategy.SuffixingRandom( PROXY_NAMING_SUFFIX, new NamingStrategy.SuffixingRandom.BaseNameResolver.ForFixedValue( persistentClass.getName() ) ) )
.subclass( interfaces.length == 1 ? persistentClass : Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING )
.implement( (Type[]) interfaces )
.method( byteBuddyState.getProxyDefinitionHelpers().getVirtualNotFinalizerFilter() )
.intercept( byteBuddyState.getProxyDefinitionHelpers().getDelegateToInterceptorDispatcherMethodDelegation() )
.method( byteBuddyState.getProxyDefinitionHelpers().getHibernateGeneratedMethodFilter() )
.method( helpers.getVirtualNotFinalizerFilter() )
.intercept( helpers.getDelegateToInterceptorDispatcherMethodDelegation() )
.method( helpers.getProxyNonInterceptedMethodFilter() )
.intercept( SuperMethodCall.INSTANCE )
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
.implement( ProxyConfiguration.class )
.intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() );
.intercept( helpers.getInterceptorFieldAccessor() );
}
public HibernateProxy deserializeProxy(SerializableProxy serializableProxy) {