diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java index 5e495b30f1..dd2097ae0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java @@ -24,6 +24,7 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.scaffold.MethodGraph; import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.pool.TypePool; +import org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy; import static net.bytebuddy.matcher.ElementMatchers.isGetter; @@ -106,6 +107,10 @@ class ByteBuddyEnhancementContext { enhancementContext.registerDiscoveredType( new UnloadedTypeDescription( typeDescription ), type ); } + public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy() { + return enhancementContext.getUnsupportedEnhancementStrategy(); + } + public void discoverCompositeTypes(TypeDescription managedCtClass, TypePool typePool) { if ( isDiscoveredType( managedCtClass ) ) { return; diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java index 7595a8ae7a..3f6f5c999e 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java @@ -25,6 +25,7 @@ import net.bytebuddy.implementation.FieldAccessor; import net.bytebuddy.implementation.FixedValue; import net.bytebuddy.implementation.Implementation; import net.bytebuddy.implementation.StubMethod; +import org.hibernate.AssertionFailure; import org.hibernate.Version; import org.hibernate.bytecode.enhance.VersionMismatchException; import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker; @@ -35,6 +36,7 @@ import org.hibernate.bytecode.enhance.spi.EnhancementInfo; import org.hibernate.bytecode.enhance.spi.Enhancer; import org.hibernate.bytecode.enhance.spi.EnhancerConstants; import org.hibernate.bytecode.enhance.spi.UnloadedField; +import org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy; import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor; import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState; import org.hibernate.engine.spi.CompositeOwner; @@ -173,7 +175,7 @@ public class EnhancerImpl implements Enhancer { } if ( enhancementContext.isEntityClass( managedCtClass ) ) { - if ( hasUnsupportedAttributeNaming( managedCtClass ) ) { + if ( checkUnsupportedAttributeNaming( managedCtClass ) ) { // do not enhance classes with mismatched names for PROPERTY-access persistent attributes return null; } @@ -337,7 +339,7 @@ public class EnhancerImpl implements Enhancer { return createTransformer( managedCtClass ).applyTo( builder ); } else if ( enhancementContext.isCompositeClass( managedCtClass ) ) { - if ( hasUnsupportedAttributeNaming( managedCtClass ) ) { + if ( checkUnsupportedAttributeNaming( managedCtClass ) ) { // do not enhance classes with mismatched names for PROPERTY-access persistent attributes return null; } @@ -377,7 +379,7 @@ public class EnhancerImpl implements Enhancer { else if ( enhancementContext.isMappedSuperclassClass( managedCtClass ) ) { // Check for HHH-16572 (PROPERTY attributes with mismatched field and method names) - if ( hasUnsupportedAttributeNaming( managedCtClass ) ) { + if ( checkUnsupportedAttributeNaming( managedCtClass ) ) { return null; } @@ -401,8 +403,22 @@ public class EnhancerImpl implements Enhancer { * Check whether an entity class ({@code managedCtClass}) has mismatched names between a persistent field and its * getter/setter when using {@link AccessType#PROPERTY}, which Hibernate does not currently support for enhancement. * See https://hibernate.atlassian.net/browse/HHH-16572 + * + * @return {@code true} if enhancement of the class must be {@link org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy#SKIP skipped} + * because it has mismatched names. + * {@code false} if enhancement of the class must proceed, either because it doesn't have any mismatched names, + * or because {@link org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy#LEGACY legacy mode} was opted into. + * @throws EnhancementException if enhancement of the class must {@link org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy#FAIL abort} because it has mismatched names. */ - private boolean hasUnsupportedAttributeNaming(TypeDescription managedCtClass) { + @SuppressWarnings("deprecation") + private boolean checkUnsupportedAttributeNaming(TypeDescription managedCtClass) { + var strategy = enhancementContext.getUnsupportedEnhancementStrategy(); + if ( UnsupportedEnhancementStrategy.LEGACY.equals( strategy ) ) { + // Don't check anything and act as if there was nothing unsupported in the class. + // This is unsafe but that's what LEGACY is about. + return false; + } + // For process access rules, See https://jakarta.ee/specifications/persistence/3.2/jakarta-persistence-spec-3.2#default-access-type // and https://jakarta.ee/specifications/persistence/3.2/jakarta-persistence-spec-3.2#a122 // @@ -464,10 +480,23 @@ public class EnhancerImpl implements Enhancer { } } } - if (propertyHasAnnotation && !propertyNameMatchesFieldName) { - log.debugf("Skipping enhancement of [%s]: due to class [%s] not having a property accessor method name matching field name [%s]", - managedCtClass, methodDescription.getDeclaringType().getActualName(), methodFieldName); - return true; + if ( propertyHasAnnotation && !propertyNameMatchesFieldName ) { + switch ( strategy ) { + case SKIP: + log.debugf( + "Skipping enhancement of [%s] because no field named [%s] could be found for property accessor method [%s]." + + " To fix this, make sure all property accessor methods have a matching field.", + managedCtClass.getName(), methodFieldName, methodDescription.getName() ); + return true; + case FAIL: + throw new EnhancementException( String.format( + "Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s]." + + " To fix this, make sure all property accessor methods have a matching field.", + managedCtClass.getName(), methodFieldName, methodDescription.getName() ) ); + default: + // We shouldn't even be in this method if using LEGACY, see top of this method. + throw new AssertionFailure( "Unexpected strategy at this point: " + strategy ); + } } } return false; diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java index 06086c65d2..453407f38c 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java @@ -7,6 +7,7 @@ package org.hibernate.bytecode.enhance.spi; import jakarta.persistence.metamodel.Type; +import org.hibernate.Incubating; /** * The context for performing an enhancement. Enhancement can happen in any number of ways: