Skip to content

Commit

Permalink
Merge pull request #5 from alfasoftware/alfa-hibernate-core-updates
Browse files Browse the repository at this point in the history
Alfa updates:
ignore shared collections, these are deliberate and there will be no changes within them (same as Alfa change in 5.4.19)
don't set the type as a side-effect of getType() method on SimpleValue (mimics behaviour of 5.4)
revert the changes committed under HHH-14869 which moved annotation detection to the earlier, metadata-construction phase rather than during session factory creation. This was only necessary to support native compilation (GraalVM) and caused issues with assignment of Alfa's custom type AlfaStringType, so was deemed the least invasive change required to restore previous behaviour (5.5 and earlier)
update version to Alfa-specific 5.6.15-alfa1001
  • Loading branch information
euano authored Aug 20, 2024
2 parents 30241bb + 8599160 commit 60315bd
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 289 deletions.
2 changes: 1 addition & 1 deletion gradle/version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
hibernateVersion=5.6.16-SNAPSHOT
hibernateVersion=5.6.15-alfa1001
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Any;
import org.hibernate.mapping.Component;
Expand Down Expand Up @@ -825,8 +823,6 @@ else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
entityBinder.processComplementaryTableDefinitions( tabAnn );

bindCallbacks( clazzToProcess, persistentClass, context );
}

/**
Expand Down Expand Up @@ -1410,32 +1406,6 @@ private static void bindTypeDef(TypeDef defAnn, MetadataBuildingContext context)

}

private static void bindCallbacks(XClass entityClass, PersistentClass persistentClass,
MetadataBuildingContext context) {
ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();

for ( CallbackType callbackType : CallbackType.values() ) {
persistentClass.addCallbackDefinitions( CallbackDefinitionResolverLegacyImpl.resolveEntityCallbacks(
reflectionManager, entityClass, callbackType ) );
}

context.getMetadataCollector().addSecondPass( new SecondPass() {
@Override
public void doSecondPass(Map persistentClasses) throws MappingException {
for ( @SuppressWarnings("unchecked") Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator();
propertyIterator.hasNext(); ) {
Property property = propertyIterator.next();
if ( property.isComposite() ) {
for ( CallbackType callbackType : CallbackType.values() ) {
property.addCallbackDefinitions( CallbackDefinitionResolverLegacyImpl.resolveEmbeddableCallbacks(
reflectionManager, persistentClass.getMappedClass(), property, callbackType ) );
}
}
}
}
} );
}

public static void bindFetchProfilesForClass(XClass clazzToProcess, MetadataBuildingContext context) {
bindFetchProfiles( clazzToProcess, context );
}
Expand Down Expand Up @@ -1480,6 +1450,7 @@ private static void bindFetchProfile(FetchProfile fetchProfileAnnotation, Metada
}
}


private static void bindDiscriminatorColumnToRootPersistentClass(
RootClass rootClass,
Ejb3DiscriminatorColumn discriminatorColumn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.CollectionType;

import org.jboss.logging.Logger;

/**
Expand Down Expand Up @@ -184,9 +183,12 @@ public static void processReachableCollection(
// who set up circular or shared references between/to collections.
if ( ce.isReached() ) {
// We've been here before
throw new HibernateException(
"Found shared references to a collection: " + type.getRole()
);

// Alfa change - ignore shared collections, these are deliberate and there will be no changes within them.
return;
// throw new HibernateException(
// "Found shared references to a collection: " + type.getRole()
// );
}

ce.setReached( true );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Consumer;

Expand All @@ -22,6 +23,9 @@
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.event.internal.CallbackRegistryImplementor;
import org.hibernate.jpa.event.internal.CallbacksFactory;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.service.spi.Stoppable;

/**
Expand All @@ -35,6 +39,7 @@ public class EventEngine {
private final EventListenerRegistry listenerRegistry;

private final CallbackRegistryImplementor callbackRegistry;
private final CallbackBuilder callbackBuilder;

public EventEngine(
MetadataImplementor mappings,
Expand All @@ -43,8 +48,33 @@ public EventEngine(
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve (JPA) callback handlers

this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions() );
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder(
sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(),
mappings.getMetadataBuildingOptions().getReflectionManager()
);

for ( PersistentClass persistentClass : mappings.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have dynamic (non-java class) mapping
continue;
}

this.callbackBuilder.buildCallbacksForEntity( persistentClass.getMappedClass(), callbackRegistry );

for ( Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator(); propertyIterator.hasNext(); ) {
final Property property = propertyIterator.next();

if ( property.isComposite() ) {
this.callbackBuilder.buildCallbacksForEmbeddable(
property,
persistentClass.getMappedClass(),
callbackRegistry
);
}
}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -162,5 +192,7 @@ public void stop() {
}

callbackRegistry.release();

callbackBuilder.release();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,97 @@
import javax.persistence.MappedSuperclass;
import javax.persistence.PersistenceException;

import org.hibernate.MappingException;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;

import org.jboss.logging.Logger;

/**
* Resolves JPA callback definitions using a HCANN ReflectionManager.
* <p>
* "legacy" in that we want to move to Jandex instead.
* EntityCallbackBuilder implementation using HCANN ReflectionManager. "legacy" in that
* we want to move to Jandex instead.
*
* @author Steve Ebersole
*/
public final class CallbackDefinitionResolverLegacyImpl {
private static final Logger log = Logger.getLogger( CallbackDefinitionResolverLegacyImpl.class );
final class CallbackBuilderLegacyImpl implements CallbackBuilder {
private static final Logger log = Logger.getLogger( CallbackBuilderLegacyImpl.class );

private final ManagedBeanRegistry managedBeanRegistry;
private final ReflectionManager reflectionManager;

CallbackBuilderLegacyImpl(ManagedBeanRegistry managedBeanRegistry, ReflectionManager reflectionManager) {
this.managedBeanRegistry = managedBeanRegistry;
this.reflectionManager = reflectionManager;
}

@Override
public void buildCallbacksForEntity(Class entityClass, CallbackRegistrar callbackRegistrar) {
for ( CallbackType callbackType : CallbackType.values() ) {
if ( callbackRegistrar.hasRegisteredCallbacks( entityClass, callbackType ) ) {
// this most likely means we have a class mapped multiple times using the hbm.xml
// "entity name" feature
if ( log.isDebugEnabled() ) {
log.debugf(
"CallbackRegistry reported that Class [%s] already had %s callbacks registered; " +
"assuming this means the class was mapped twice " +
"(using hbm.xml entity-name support) - skipping subsequent registrations",
entityClass.getName(),
callbackType.getCallbackAnnotation().getSimpleName()
);
}
continue;
}
final Callback[] callbacks = resolveEntityCallbacks( entityClass, callbackType, reflectionManager );
callbackRegistrar.registerCallbacks( entityClass, callbacks );
}
}

@Override
public void buildCallbacksForEmbeddable(
Property embeddableProperty, Class entityClass, CallbackRegistrar callbackRegistrar) {
for ( CallbackType callbackType : CallbackType.values() ) {
final Callback[] callbacks = resolveEmbeddableCallbacks(
entityClass,
embeddableProperty,
callbackType,
reflectionManager
);
callbackRegistrar.registerCallbacks( entityClass, callbacks );
}
}

@Override
public void release() {
// nothing to do
}

@SuppressWarnings({"unchecked", "WeakerAccess"})
public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager reflectionManager,
XClass entityClass, CallbackType callbackType) {
List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
public Callback[] resolveEntityCallbacks(Class entityClass, CallbackType callbackType, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<>();
List<String> callbacksMethodNames = new ArrayList<>();
List<Class> orderedListeners = new ArrayList<>();
XClass currentClazz = entityClass;
XClass currentClazz = reflectionManager.toXClass( entityClass );
boolean stopListeners = false;
boolean stopDefaultListeners = false;
do {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new EntityCallback.Definition( method, callbackType );
if ( callback == null ) {
callback = new EntityCallback( method, callbackType );
Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) {
Expand All @@ -78,7 +127,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
entityClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacks.add( 0, callback ); //superclass first
callbacksMethodNames.add( 0, methodName );
}
else {
Expand Down Expand Up @@ -119,7 +168,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
}

for ( Class listener : orderedListeners ) {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
if ( listener != null ) {
XClass xListener = reflectionManager.toXClass( listener );
callbacksMethodNames = new ArrayList<>();
Expand All @@ -130,8 +179,12 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new ListenerCallback.Definition( listener, method, callbackType );
if ( callback == null ) {
callback = new ListenerCallback(
managedBeanRegistry.getBean( listener ),
method,
callbackType
);

Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
Expand All @@ -150,7 +203,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
entityClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); // listeners first
callbacks.add( 0, callback ); // listeners first
}
else {
throw new PersistenceException(
Expand All @@ -165,29 +218,29 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
}
}
}
return callbackDefinitions;
return callbacks.toArray( new Callback[callbacks.size()] );
}

public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionManager reflectionManager,
Class<?> entityClass, Property embeddableProperty,
CallbackType callbackType) {
@SuppressWarnings({"unchecked", "WeakerAccess"})
public Callback[] resolveEmbeddableCallbacks(Class entityClass, Property embeddableProperty, CallbackType callbackType, ReflectionManager reflectionManager) {

final Class embeddableClass = embeddableProperty.getType().getReturnedClass();
final XClass embeddableXClass = reflectionManager.toXClass( embeddableClass );
final Getter embeddableGetter = embeddableProperty.getGetter( entityClass );
final List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
final List<Callback> callbacks = new ArrayList<>();
final List<String> callbacksMethodNames = new ArrayList<>();
XClass currentClazz = embeddableXClass;
do {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new EmbeddableCallback.Definition( embeddableGetter, method, callbackType );
if ( callback == null ) {
callback = new EmbeddableCallback( embeddableGetter, method, callbackType );
Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) {
Expand All @@ -205,7 +258,7 @@ public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionMana
embeddableXClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacks.add( 0, callback ); //superclass first
callbacksMethodNames.add( 0, methodName );
}
else {
Expand All @@ -225,7 +278,7 @@ public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionMana
}
while ( currentClazz != null );

return callbackDefinitions;
return callbacks.toArray( new Callback[callbacks.size()] );
}

private static boolean useAnnotationAnnotatedByListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ public void registerCallbacks(Class entityClass, Callback[] callbacks) {
return;
}

for ( Callback callback : callbacks ) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callback.getCallbackType() );
Callback[] entityCallbacks = map.get( entityClass );
if ( entityCallbacks == null ) {
entityCallbacks = new Callback[0];
}
entityCallbacks = ArrayHelper.join( entityCallbacks, callback );
map.put( entityClass, entityCallbacks );
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbacks[0].getCallbackType() );
Callback[] entityCallbacks = map.get( entityClass );

if ( entityCallbacks != null ) {
callbacks = ArrayHelper.join( entityCallbacks, callbacks );
}
map.put( entityClass, callbacks );
}

@Override
Expand Down
Loading

0 comments on commit 60315bd

Please sign in to comment.