HHH-15804 Avoid JDK functional interfaces in ManagedTypeHelper

This commit is contained in:
franz1981 2022-12-02 15:49:58 +01:00 committed by Sanne Grinovero
parent c114d08ac2
commit 3c535c544f
1 changed files with 29 additions and 4 deletions

View File

@ -18,7 +18,6 @@ import org.hibernate.proxy.HibernateProxy;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* This is a helper to encapsulate an optimal strategy to execute type checks
@ -167,6 +166,17 @@ public final class ManagedTypeHelper {
return false;
}
/**
* This interface has been introduced to mitigate <a href="https://bugs.openjdk.org/browse/JDK-8180450">JDK-8180450</a>.<br>
* Sadly, using {@code BiConsumer} will trigger a type pollution issue because of generics type-erasure:
* {@code BiConsumer}'s actual parameters types on the lambda implemention's
* {@link BiConsumer#accept} are stealthy enforced via {@code checkcast}, messing up with type check cached data.
*/
@FunctionalInterface
public interface PersistentAttributeInterceptableAction<T> {
void accept(PersistentAttributeInterceptable interceptable, T optionalParam);
}
/**
* Helper to execute an action on an entity, but exclusively if it's implementing the {@see PersistentAttributeInterceptable}
* interface. Otherwise no action is performed.
@ -178,7 +188,7 @@ public final class ManagedTypeHelper {
*/
public static <T> void processIfPersistentAttributeInterceptable(
final Object entity,
final BiConsumer<PersistentAttributeInterceptable, T> action,
final PersistentAttributeInterceptableAction<T> action,
final T optionalParam) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
final PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
@ -196,7 +206,7 @@ public final class ManagedTypeHelper {
* @param entity
* @param action
*/
public static void processIfSelfDirtinessTracker(final Object entity, final Consumer<SelfDirtinessTracker> action) {
public static void processIfSelfDirtinessTracker(final Object entity, final SelfDirtinessTrackerConsumer action) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
final PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
final SelfDirtinessTracker e = t.asSelfDirtinessTracker();
@ -206,6 +216,13 @@ public final class ManagedTypeHelper {
}
}
// Not using Consumer<SelfDirtinessTracker> because of JDK-8180450:
// use a custom functional interface with explicit type.
@FunctionalInterface
public interface SelfDirtinessTrackerConsumer {
void accept(SelfDirtinessTracker tracker);
}
/**
* If the entity is implementing SelfDirtinessTracker, apply some action to it; this action should take
* a parameter of type T.
@ -218,7 +235,7 @@ public final class ManagedTypeHelper {
*/
public static <T> void processIfSelfDirtinessTracker(
final Object entity,
final BiConsumer<SelfDirtinessTracker, T> action,
final SelfDirtinessTrackerAction<T> action,
final T optionalParam) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
final PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
@ -229,6 +246,13 @@ public final class ManagedTypeHelper {
}
}
// Not using BiConsumer<SelfDirtinessTracker, T> because of JDK-8180450:
// use a custom functional interface with explicit type.
@FunctionalInterface
public interface SelfDirtinessTrackerAction<T> {
void accept(SelfDirtinessTracker tracker, T optionalParam);
}
/**
* Cast the object to PersistentAttributeInterceptable
* (using this is highly preferrable over a direct cast)
@ -304,6 +328,7 @@ public final class ManagedTypeHelper {
}
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to CompositeTracker" );
}
/**
* Cast the object to CompositeOwner
* (using this is highly preferrable over a direct cast)