Merge remote-tracking branch 'upstream/main' into wip/6.0_merge

This commit is contained in:
Andrea Boriero 2021-10-15 12:07:14 +02:00
commit c545cee28c
15 changed files with 283 additions and 187 deletions

View File

@ -101,6 +101,8 @@ import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper; 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.loader.PropertyPath;
import org.hibernate.mapping.Any; import org.hibernate.mapping.Any;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
@ -837,6 +839,8 @@ public final class AnnotationBinder {
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) ); entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) ); entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
entityBinder.processComplementaryTableDefinitions( tabAnn ); entityBinder.processComplementaryTableDefinitions( tabAnn );
bindCallbacks( clazzToProcess, persistentClass, context );
} }
private static void handleTypeDescriptorRegistrations(XAnnotatedElement annotatedElement, MetadataBuildingContext context) { private static void handleTypeDescriptorRegistrations(XAnnotatedElement annotatedElement, MetadataBuildingContext context) {
@ -1432,6 +1436,32 @@ public final class AnnotationBinder {
context.getMetadataCollector().addFilterDefinition( def ); context.getMetadataCollector().addFilterDefinition( def );
} }
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) { public static void bindFetchProfilesForClass(XClass clazzToProcess, MetadataBuildingContext context) {
bindFetchProfiles( clazzToProcess, context ); bindFetchProfiles( clazzToProcess, context );
} }
@ -1476,7 +1506,6 @@ public final class AnnotationBinder {
} }
} }
private static void bindDiscriminatorColumnToRootPersistentClass( private static void bindDiscriminatorColumnToRootPersistentClass(
RootClass rootClass, RootClass rootClass,
Ejb3DiscriminatorColumn discriminatorColumn, Ejb3DiscriminatorColumn discriminatorColumn,

View File

@ -9,7 +9,6 @@ package org.hibernate.event.spi;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -23,9 +22,6 @@ import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.event.internal.CallbackRegistryImplementor; import org.hibernate.jpa.event.internal.CallbackRegistryImplementor;
import org.hibernate.jpa.event.internal.CallbacksFactory; 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; import org.hibernate.service.spi.Stoppable;
/** /**
@ -39,7 +35,6 @@ public class EventEngine {
private final EventListenerRegistry listenerRegistry; private final EventListenerRegistry listenerRegistry;
private final CallbackRegistryImplementor callbackRegistry; private final CallbackRegistryImplementor callbackRegistry;
private final CallbackBuilder callbackBuilder;
public EventEngine( public EventEngine(
MetadataImplementor mappings, MetadataImplementor mappings,
@ -48,33 +43,8 @@ public class EventEngine {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve (JPA) callback handlers // resolve (JPA) callback handlers
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions() ); this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder( sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );
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
);
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -192,7 +162,5 @@ public class EventEngine {
} }
callbackRegistry.release(); callbackRegistry.release();
callbackBuilder.release();
} }
} }

View File

@ -19,88 +19,39 @@ import jakarta.persistence.ExcludeSuperclassListeners;
import jakarta.persistence.MappedSuperclass; import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PersistenceException; import jakarta.persistence.PersistenceException;
import org.hibernate.MappingException;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod; import org.hibernate.annotations.common.reflection.XMethod;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.jpa.event.spi.Callback; import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackType; import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
/** /**
* EntityCallbackBuilder implementation using HCANN ReflectionManager. "legacy" in that * Resolves JPA callback definitions using a HCANN ReflectionManager.
* we want to move to Jandex instead. * <p>
* "legacy" in that we want to move to Jandex instead.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
final class CallbackBuilderLegacyImpl implements CallbackBuilder { public final class CallbackDefinitionResolverLegacyImpl {
private static final Logger log = Logger.getLogger( CallbackBuilderLegacyImpl.class ); private static final Logger log = Logger.getLogger( CallbackDefinitionResolverLegacyImpl.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"}) @SuppressWarnings({"unchecked", "WeakerAccess"})
public Callback[] resolveEntityCallbacks(Class entityClass, CallbackType callbackType, ReflectionManager reflectionManager) { public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager reflectionManager,
List<Callback> callbacks = new ArrayList<>(); XClass entityClass, CallbackType callbackType) {
List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
List<String> callbacksMethodNames = new ArrayList<>(); List<String> callbacksMethodNames = new ArrayList<>();
List<Class> orderedListeners = new ArrayList<>(); List<Class> orderedListeners = new ArrayList<>();
XClass currentClazz = reflectionManager.toXClass( entityClass ); XClass currentClazz = entityClass;
boolean stopListeners = false; boolean stopListeners = false;
boolean stopDefaultListeners = false; boolean stopDefaultListeners = false;
do { do {
Callback callback = null; CallbackDefinition callbackDefinition = null;
List<XMethod> methods = currentClazz.getDeclaredMethods(); List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) { for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) { if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
@ -108,8 +59,8 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
final String methodName = method.getName(); final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) { if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method //overridden method, remove the superclass overridden method
if ( callback == null ) { if ( callbackDefinition == null ) {
callback = new EntityCallback( method, callbackType ); callbackDefinition = new EntityCallback.Definition( method, callbackType );
Class returnType = method.getReturnType(); Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes(); Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) { if ( returnType != Void.TYPE || args.length != 0 ) {
@ -127,7 +78,7 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
entityClass.getName() entityClass.getName()
); );
} }
callbacks.add( 0, callback ); //superclass first callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacksMethodNames.add( 0, methodName ); callbacksMethodNames.add( 0, methodName );
} }
else { else {
@ -168,7 +119,7 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
} }
for ( Class listener : orderedListeners ) { for ( Class listener : orderedListeners ) {
Callback callback = null; CallbackDefinition callbackDefinition = null;
if ( listener != null ) { if ( listener != null ) {
XClass xListener = reflectionManager.toXClass( listener ); XClass xListener = reflectionManager.toXClass( listener );
callbacksMethodNames = new ArrayList<>(); callbacksMethodNames = new ArrayList<>();
@ -179,12 +130,8 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
final String methodName = method.getName(); final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) { if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method //overridden method, remove the superclass overridden method
if ( callback == null ) { if ( callbackDefinition == null ) {
callback = new ListenerCallback( callbackDefinition = new ListenerCallback.Definition( listener, method, callbackType );
managedBeanRegistry.getBean( listener ),
method,
callbackType
);
Class returnType = method.getReturnType(); Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes(); Class[] args = method.getParameterTypes();
@ -203,7 +150,7 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
entityClass.getName() entityClass.getName()
); );
} }
callbacks.add( 0, callback ); // listeners first callbackDefinitions.add( 0, callbackDefinition ); // listeners first
} }
else { else {
throw new PersistenceException( throw new PersistenceException(
@ -218,20 +165,20 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
} }
} }
} }
return callbacks.toArray( new Callback[callbacks.size()] ); return callbackDefinitions;
} }
@SuppressWarnings({"unchecked", "WeakerAccess"}) public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionManager reflectionManager,
public Callback[] resolveEmbeddableCallbacks(Class entityClass, Property embeddableProperty, CallbackType callbackType, ReflectionManager reflectionManager) { Class<?> entityClass, Property embeddableProperty,
CallbackType callbackType) {
final Class embeddableClass = embeddableProperty.getType().getReturnedClass(); final Class embeddableClass = embeddableProperty.getType().getReturnedClass();
final XClass embeddableXClass = reflectionManager.toXClass( embeddableClass ); final XClass embeddableXClass = reflectionManager.toXClass( embeddableClass );
final Getter embeddableGetter = embeddableProperty.getGetter( entityClass ); final Getter embeddableGetter = embeddableProperty.getGetter( entityClass );
final List<Callback> callbacks = new ArrayList<>(); final List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
final List<String> callbacksMethodNames = new ArrayList<>(); final List<String> callbacksMethodNames = new ArrayList<>();
XClass currentClazz = embeddableXClass; XClass currentClazz = embeddableXClass;
do { do {
Callback callback = null; CallbackDefinition callbackDefinition = null;
List<XMethod> methods = currentClazz.getDeclaredMethods(); List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) { for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) { if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
@ -239,8 +186,8 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
final String methodName = method.getName(); final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) { if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method //overridden method, remove the superclass overridden method
if ( callback == null ) { if ( callbackDefinition == null ) {
callback = new EmbeddableCallback( embeddableGetter, method, callbackType ); callbackDefinition = new EmbeddableCallback.Definition( embeddableGetter, method, callbackType );
Class returnType = method.getReturnType(); Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes(); Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) { if ( returnType != Void.TYPE || args.length != 0 ) {
@ -258,7 +205,7 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
embeddableXClass.getName() embeddableXClass.getName()
); );
} }
callbacks.add( 0, callback ); //superclass first callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacksMethodNames.add( 0, methodName ); callbacksMethodNames.add( 0, methodName );
} }
else { else {
@ -278,7 +225,7 @@ final class CallbackBuilderLegacyImpl implements CallbackBuilder {
} }
while ( currentClazz != null ); while ( currentClazz != null );
return callbacks.toArray( new Callback[callbacks.size()] ); return callbackDefinitions;
} }
private static boolean useAnnotationAnnotatedByListener; private static boolean useAnnotationAnnotatedByListener;

View File

@ -41,13 +41,15 @@ final class CallbackRegistryImpl implements CallbackRegistryImplementor {
return; return;
} }
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbacks[0].getCallbackType() ); for ( Callback callback : callbacks ) {
Callback[] entityCallbacks = map.get( entityClass ); final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callback.getCallbackType() );
Callback[] entityCallbacks = map.get( entityClass );
if ( entityCallbacks != null ) { if ( entityCallbacks == null ) {
callbacks = ArrayHelper.join( entityCallbacks, callbacks ); entityCallbacks = new Callback[0];
}
entityCallbacks = ArrayHelper.join( entityCallbacks, callback );
map.put( entityClass, entityCallbacks );
} }
map.put( entityClass, callbacks );
} }
@Override @Override

View File

@ -7,9 +7,9 @@
package org.hibernate.jpa.event.internal; package org.hibernate.jpa.event.internal;
import org.hibernate.jpa.event.spi.CallbackBuilder; import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackRegistry; import org.hibernate.jpa.event.spi.CallbackRegistrar;
public interface CallbackRegistryImplementor extends CallbackRegistry, CallbackBuilder.CallbackRegistrar { public interface CallbackRegistryImplementor extends CallbackRegistrar, CallbackBuilder.CallbackRegistrar {
void release(); void release();

View File

@ -6,42 +6,89 @@
*/ */
package org.hibernate.jpa.event.internal; package org.hibernate.jpa.event.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackBuilder; import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;
/** /**
* The intent of this class is to use a lighter implementation * The intent of this class is to use a lighter implementation
* when JPA callbacks are disabled via * when JPA callbacks are disabled via
* {@link SessionFactoryOptions#areJPACallbacksEnabled()} * {@link SessionFactoryOptions#areJPACallbacksEnabled()}
*/ */
public final class CallbacksFactory { public final class CallbacksFactory {
public static CallbackRegistryImplementor buildCallbackRegistry(SessionFactoryOptions options) { private static final Logger log = Logger.getLogger( CallbacksFactory.class );
if ( jpaCallBacksEnabled( options ) ) {
return new CallbackRegistryImpl(); public static CallbackRegistryImplementor buildCallbackRegistry(SessionFactoryOptions options,
} ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
else { if ( !jpaCallBacksEnabled( options ) ) {
return new EmptyCallbackRegistryImpl(); return new EmptyCallbackRegistryImpl();
} }
ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
CallbackRegistryImplementor registry = new CallbackRegistryImpl();
Set<Class<?>> entityClasses = new HashSet<>();
for ( PersistentClass persistentClass : entityBindings ) {
if ( persistentClass.getClassName() == null ) {
// we can have dynamic (non-java class) mapping
continue;
}
Class<?> entityClass = persistentClass.getMappedClass();
if ( !entityClasses.add( entityClass ) ) {
// this most likely means we have a class mapped multiple times using the hbm.xml
// "entity name" feature
if ( log.isDebugEnabled() ) {
log.debugf(
"Class [%s] already has callbacks registered; " +
"assuming this means the class was mapped twice " +
"(using hbm.xml entity-name support) - skipping subsequent registrations" +
"to avoid duplicates",
entityClass.getName()
);
}
continue;
}
registry.registerCallbacks( persistentClass.getMappedClass(),
buildCallbacks( persistentClass.getCallbackDefinitions(), beanRegistry ) );
for ( @SuppressWarnings("unchecked") Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator();
propertyIterator.hasNext(); ) {
final Property property = propertyIterator.next();
registry.registerCallbacks( persistentClass.getMappedClass(),
buildCallbacks( property.getCallbackDefinitions(), beanRegistry ) );
}
}
return registry;
} }
public static CallbackBuilder buildCallbackBuilder( private static Callback[] buildCallbacks(List<CallbackDefinition> callbackDefinitions,
SessionFactoryOptions options, ManagedBeanRegistry beanRegistry) {
ServiceRegistry serviceRegistry, if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
ReflectionManager reflectionManager) { return null;
if ( jpaCallBacksEnabled( options ) ) {
final ManagedBeanRegistry managedBeanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
return new CallbackBuilderLegacyImpl(
managedBeanRegistry,
reflectionManager
);
} }
else { List<Callback> callbacks = new ArrayList<>();
return new EmptyCallbackBuilder(); for ( CallbackDefinition definition : callbackDefinitions ) {
callbacks.add( definition.createCallback( beanRegistry ) );
} }
return callbacks.toArray( new Callback[0] );
} }
private static boolean jpaCallBacksEnabled(SessionFactoryOptions options) { private static boolean jpaCallBacksEnabled(SessionFactoryOptions options) {

View File

@ -9,8 +9,11 @@ package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.CallbackType; import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
/** /**
* Represents a JPA callback on the embeddable type * Represents a JPA callback on the embeddable type
@ -19,10 +22,27 @@ import org.hibernate.property.access.spi.Getter;
*/ */
final class EmbeddableCallback extends AbstractCallback { final class EmbeddableCallback extends AbstractCallback {
public static class Definition implements CallbackDefinition {
private final Getter embeddableGetter;
private final Method callbackMethod;
private final CallbackType callbackType;
public Definition(Getter embeddableGetter, Method callbackMethod, CallbackType callbackType) {
this.embeddableGetter = embeddableGetter;
this.callbackMethod = callbackMethod;
this.callbackType = callbackType;
}
@Override
public Callback createCallback(ManagedBeanRegistry beanRegistry) {
return new EmbeddableCallback( embeddableGetter, callbackMethod, callbackType );
}
}
private final Getter embeddableGetter; private final Getter embeddableGetter;
private final Method callbackMethod; private final Method callbackMethod;
EmbeddableCallback(Getter embeddableGetter, Method callbackMethod, CallbackType callbackType) { private EmbeddableCallback(Getter embeddableGetter, Method callbackMethod, CallbackType callbackType) {
super( callbackType ); super( callbackType );
this.embeddableGetter = embeddableGetter; this.embeddableGetter = embeddableGetter;
this.callbackMethod = callbackMethod; this.callbackMethod = callbackMethod;

View File

@ -1,29 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.jpa.event.internal;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.mapping.Property;
final class EmptyCallbackBuilder implements CallbackBuilder {
@Override
public void buildCallbacksForEntity(Class entityClass, CallbackRegistrar callbackRegistrar) {
//no-op
}
@Override
public void buildCallbacksForEmbeddable(Property embeddableProperty, Class entityClass, CallbackRegistrar callbackRegistrar) {
//no-op
}
@Override
public void release() {
//no-op
}
}

View File

@ -9,7 +9,10 @@ package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.CallbackType; import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
/** /**
* Represents a JPA callback on the entity itself * Represents a JPA callback on the entity itself
@ -19,9 +22,24 @@ import org.hibernate.jpa.event.spi.CallbackType;
*/ */
final class EntityCallback extends AbstractCallback { final class EntityCallback extends AbstractCallback {
public static class Definition implements CallbackDefinition {
private final Method callbackMethod;
private final CallbackType callbackType;
public Definition(Method callbackMethod, CallbackType callbackType) {
this.callbackMethod = callbackMethod;
this.callbackType = callbackType;
}
@Override
public Callback createCallback(ManagedBeanRegistry beanRegistry) {
return new EntityCallback( callbackMethod, callbackType );
}
}
private final Method callbackMethod; private final Method callbackMethod;
EntityCallback(Method callbackMethod, CallbackType callbackType) { private EntityCallback(Method callbackMethod, CallbackType callbackType) {
super( callbackType ); super( callbackType );
this.callbackMethod = callbackMethod; this.callbackMethod = callbackMethod;
} }

View File

@ -9,8 +9,11 @@ package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.CallbackType; import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.resource.beans.spi.ManagedBean; import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
/** /**
* Represents a JPA callback using a dedicated listener * Represents a JPA callback using a dedicated listener
@ -20,10 +23,27 @@ import org.hibernate.resource.beans.spi.ManagedBean;
*/ */
class ListenerCallback extends AbstractCallback { class ListenerCallback extends AbstractCallback {
private final Method callbackMethod; public static class Definition implements CallbackDefinition {
private final ManagedBean listenerManagedBean; private final Class<?> listenerClass;
private final Method callbackMethod;
private final CallbackType callbackType;
ListenerCallback(ManagedBean listenerManagedBean, Method callbackMethod, CallbackType callbackType) { public Definition(Class<?> listenerClass, Method callbackMethod, CallbackType callbackType) {
this.listenerClass = listenerClass;
this.callbackMethod = callbackMethod;
this.callbackType = callbackType;
}
@Override
public Callback createCallback(ManagedBeanRegistry beanRegistry) {
return new ListenerCallback( beanRegistry.getBean( listenerClass ), callbackMethod, callbackType );
}
}
private final Method callbackMethod;
private final ManagedBean<?> listenerManagedBean;
ListenerCallback(ManagedBean<?> listenerManagedBean, Method callbackMethod, CallbackType callbackType) {
super( callbackType ); super( callbackType );
this.listenerManagedBean = listenerManagedBean; this.listenerManagedBean = listenerManagedBean;
this.callbackMethod = callbackMethod; this.callbackMethod = callbackMethod;

View File

@ -12,20 +12,18 @@ import org.hibernate.mapping.Property;
* Contract for walking an entity hierarchy and building a list of JPA callbacks * Contract for walking an entity hierarchy and building a list of JPA callbacks
* *
* @author Steve Ebersole * @author Steve Ebersole
*
* @deprecated This SPI has never been functional and is no longer used. It will eventually be removed.
*/ */
@Deprecated
public interface CallbackBuilder { public interface CallbackBuilder {
/** /**
* Represents the target of JPA callback registrations as part the EntityCallbackBuilder * Represents the target of JPA callback registrations as part the EntityCallbackBuilder
*
* @deprecated Use {@link org.hibernate.jpa.event.spi.CallbackRegistrar} instead.
*/ */
interface CallbackRegistrar extends CallbackRegistry { @Deprecated
interface CallbackRegistrar extends org.hibernate.jpa.event.spi.CallbackRegistrar {
/**
* Register the callback against the given entity.
*
* @param entityClass The entity Class to register the Callbacks against
* @param callbacks The Callbacks to register against the given entity Class
*/
void registerCallbacks(Class entityClass, Callback[] callbacks);
} }
void buildCallbacksForEntity(Class entityClass, CallbackRegistrar callbackRegistrar); void buildCallbacksForEntity(Class entityClass, CallbackRegistrar callbackRegistrar);

View File

@ -0,0 +1,17 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.jpa.event.spi;
import java.io.Serializable;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
public interface CallbackDefinition extends Serializable {
Callback createCallback(ManagedBeanRegistry beanRegistry);
}

View File

@ -0,0 +1,19 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.jpa.event.spi;
public interface CallbackRegistrar extends CallbackRegistry {
/**
* Register the callback against the given entity.
*
* @param entityClass The entity Class to register the Callbacks against
* @param callbacks The Callbacks to register against the given entity Class
*/
void registerCallbacks(Class entityClass, Callback[] callbacks);
}

View File

@ -29,6 +29,7 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.JoinedIterator; import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.internal.util.collections.SingletonIterator; import org.hibernate.internal.util.collections.SingletonIterator;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.Alias; import org.hibernate.sql.Alias;
@ -76,6 +77,7 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
private Boolean isAbstract; private Boolean isAbstract;
private boolean hasSubselectLoadableCollections; private boolean hasSubselectLoadableCollections;
private Component identifierMapper; private Component identifierMapper;
private java.util.List<CallbackDefinition> callbackDefinitions;
// Custom SQL // Custom SQL
private String customSQLInsert; private String customSQLInsert;
@ -992,6 +994,23 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
return identifierMapper != null; return identifierMapper != null;
} }
public void addCallbackDefinitions(java.util.List<CallbackDefinition> callbackDefinitions) {
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
return;
}
if ( this.callbackDefinitions == null ) {
this.callbackDefinitions = new ArrayList<>();
}
this.callbackDefinitions.addAll( callbackDefinitions );
}
public java.util.List<CallbackDefinition> getCallbackDefinitions() {
if ( callbackDefinitions == null ) {
return Collections.emptyList();
}
return Collections.unmodifiableList( callbackDefinitions );
}
public void setIdentifierMapper(Component handle) { public void setIdentifierMapper(Component handle) {
this.identifierMapper = handle; this.identifierMapper = handle;
} }

View File

@ -7,6 +7,8 @@
package org.hibernate.mapping; package org.hibernate.mapping;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -18,6 +20,7 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccessStrategy; import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.property.access.spi.PropertyAccessStrategyResolver; import org.hibernate.property.access.spi.PropertyAccessStrategyResolver;
@ -49,6 +52,7 @@ public class Property implements Serializable, MetaAttributable {
private PersistentClass persistentClass; private PersistentClass persistentClass;
private boolean naturalIdentifier; private boolean naturalIdentifier;
private boolean lob; private boolean lob;
private java.util.List<CallbackDefinition> callbackDefinitions;
public boolean isBackRef() { public boolean isBackRef() {
return false; return false;
@ -360,4 +364,21 @@ public class Property implements Serializable, MetaAttributable {
this.lob = lob; this.lob = lob;
} }
public void addCallbackDefinitions(java.util.List<CallbackDefinition> callbackDefinitions) {
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
return;
}
if ( this.callbackDefinitions == null ) {
this.callbackDefinitions = new ArrayList<>();
}
this.callbackDefinitions.addAll( callbackDefinitions );
}
public java.util.List<CallbackDefinition> getCallbackDefinitions() {
if ( callbackDefinitions == null ) {
return Collections.emptyList();
}
return Collections.unmodifiableList( callbackDefinitions );
}
} }