HHH-17460 - Ongoing JPA 32 work
This commit is contained in:
parent
9b46ced2b3
commit
808544579c
|
@ -63,7 +63,6 @@ import org.hibernate.annotations.Tables;
|
||||||
import org.hibernate.annotations.TypeBinderType;
|
import org.hibernate.annotations.TypeBinderType;
|
||||||
import org.hibernate.annotations.View;
|
import org.hibernate.annotations.View;
|
||||||
import org.hibernate.annotations.Where;
|
import org.hibernate.annotations.Where;
|
||||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
|
||||||
import org.hibernate.binder.TypeBinder;
|
import org.hibernate.binder.TypeBinder;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||||
|
@ -74,6 +73,7 @@ import org.hibernate.boot.model.naming.ImplicitEntityNameSource;
|
||||||
import org.hibernate.boot.model.naming.NamingStrategyHelper;
|
import org.hibernate.boot.model.naming.NamingStrategyHelper;
|
||||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||||
import org.hibernate.boot.models.HibernateAnnotations;
|
import org.hibernate.boot.models.HibernateAnnotations;
|
||||||
|
import org.hibernate.boot.models.categorize.spi.JpaEventListener;
|
||||||
import org.hibernate.boot.spi.AccessType;
|
import org.hibernate.boot.spi.AccessType;
|
||||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
@ -85,6 +85,7 @@ import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.jdbc.Expectation;
|
import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.jpa.event.internal.CallbackDefinitionResolver;
|
||||||
import org.hibernate.jpa.event.spi.CallbackType;
|
import org.hibernate.jpa.event.spi.CallbackType;
|
||||||
import org.hibernate.mapping.BasicValue;
|
import org.hibernate.mapping.BasicValue;
|
||||||
import org.hibernate.mapping.CheckConstraint;
|
import org.hibernate.mapping.CheckConstraint;
|
||||||
|
@ -166,8 +167,6 @@ import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||||
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
|
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
|
||||||
import static org.hibernate.internal.util.StringHelper.unqualify;
|
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||||
import static org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl.resolveEmbeddableCallbacks;
|
|
||||||
import static org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl.resolveEntityCallbacks;
|
|
||||||
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
||||||
|
|
||||||
|
|
||||||
|
@ -655,7 +654,7 @@ public class EntityBinder {
|
||||||
propertyAccessor,
|
propertyAccessor,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
final InheritanceState state = inheritanceStates.get( idPropertyOnBaseClass.getClassOrElementType() );
|
final InheritanceState state = inheritanceStates.get( idPropertyOnBaseClass.getClassOrElementType().determineRawClass() );
|
||||||
if ( state == null ) {
|
if ( state == null ) {
|
||||||
return false; //while it is likely a user error, let's consider it is something that might happen
|
return false; //while it is likely a user error, let's consider it is something that might happen
|
||||||
}
|
}
|
||||||
|
@ -687,11 +686,10 @@ public class EntityBinder {
|
||||||
|
|
||||||
// Fill simple value and property since and Id is a property
|
// Fill simple value and property since and Id is a property
|
||||||
final PersistentClass persistentClass = propertyHolder.getPersistentClass();
|
final PersistentClass persistentClass = propertyHolder.getPersistentClass();
|
||||||
if ( !(persistentClass instanceof RootClass) ) {
|
if ( !( persistentClass instanceof RootClass rootClass ) ) {
|
||||||
throw new AnnotationException( "Entity '" + persistentClass.getEntityName()
|
throw new AnnotationException( "Entity '" + persistentClass.getEntityName()
|
||||||
+ "' is a subclass in an entity inheritance hierarchy and may not redefine the identifier of the root entity" );
|
+ "' is a subclass in an entity inheritance hierarchy and may not redefine the identifier of the root entity" );
|
||||||
}
|
}
|
||||||
final RootClass rootClass = (RootClass) persistentClass;
|
|
||||||
final Component id = fillEmbeddable(
|
final Component id = fillEmbeddable(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
|
@ -1225,17 +1223,29 @@ public class EntityBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link JpaEventListener} for a better (?) alternative
|
||||||
|
*/
|
||||||
private static void bindCallbacks(ClassDetails entityClass, PersistentClass persistentClass, MetadataBuildingContext context) {
|
private static void bindCallbacks(ClassDetails entityClass, PersistentClass persistentClass, MetadataBuildingContext context) {
|
||||||
final ReflectionManager reflection = context.getBootstrapContext().getReflectionManager();
|
|
||||||
for ( CallbackType callbackType : CallbackType.values() ) {
|
for ( CallbackType callbackType : CallbackType.values() ) {
|
||||||
persistentClass.addCallbackDefinitions( resolveEntityCallbacks( reflection, entityClass, callbackType ) );
|
persistentClass.addCallbackDefinitions( CallbackDefinitionResolver.resolveEntityCallbacks(
|
||||||
|
context,
|
||||||
|
entityClass,
|
||||||
|
callbackType
|
||||||
|
) );
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getMetadataCollector().addSecondPass( persistentClasses -> {
|
context.getMetadataCollector().addSecondPass( persistentClasses -> {
|
||||||
for ( Property property : persistentClass.getDeclaredProperties() ) {
|
for ( Property property : persistentClass.getDeclaredProperties() ) {
|
||||||
final Class<?> mappedClass = persistentClass.getMappedClass();
|
final Class<?> mappedClass = persistentClass.getMappedClass();
|
||||||
if ( property.isComposite() ) {
|
if ( property.isComposite() ) {
|
||||||
for ( CallbackType type : CallbackType.values() ) {
|
for ( CallbackType type : CallbackType.values() ) {
|
||||||
property.addCallbackDefinitions( resolveEmbeddableCallbacks( reflection, mappedClass, property, type ) );
|
property.addCallbackDefinitions( CallbackDefinitionResolver.resolveEmbeddableCallbacks(
|
||||||
|
context,
|
||||||
|
mappedClass,
|
||||||
|
property,
|
||||||
|
type
|
||||||
|
) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2101,39 +2111,6 @@ public class EntityBinder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends Annotation> String tableMember(Class<T> annotationType, T sqlAnnotation) {
|
|
||||||
if (SQLInsert.class == annotationType) {
|
|
||||||
return ((SQLInsert) sqlAnnotation).table();
|
|
||||||
}
|
|
||||||
else if (SQLUpdate.class == annotationType) {
|
|
||||||
return ((SQLUpdate) sqlAnnotation).table();
|
|
||||||
}
|
|
||||||
else if (SQLDelete.class == annotationType) {
|
|
||||||
return ((SQLDelete) sqlAnnotation).table();
|
|
||||||
}
|
|
||||||
else if (SQLDeleteAll.class == annotationType) {
|
|
||||||
return ((SQLDeleteAll) sqlAnnotation).table();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionFailure("Unknown annotation type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends Annotation> Annotation[] valueMember(Class<T> repeatableType, T sqlAnnotation) {
|
|
||||||
if (SQLInserts.class == repeatableType) {
|
|
||||||
return ((SQLInserts) sqlAnnotation).value();
|
|
||||||
}
|
|
||||||
else if (SQLUpdates.class == repeatableType) {
|
|
||||||
return ((SQLUpdates) sqlAnnotation).value();
|
|
||||||
}
|
|
||||||
else if (SQLDeletes.class == repeatableType) {
|
|
||||||
return ((SQLDeletes) sqlAnnotation).value();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionFailure("Unknown annotation type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Used for @*ToMany @JoinTable
|
//Used for @*ToMany @JoinTable
|
||||||
public Join addJoinTable(AnnotationUsage<JoinTable> joinTable, PropertyHolder holder, boolean noDelayInPkColumnCreation) {
|
public Join addJoinTable(AnnotationUsage<JoinTable> joinTable, PropertyHolder holder, boolean noDelayInPkColumnCreation) {
|
||||||
return addJoin(
|
return addJoin(
|
||||||
|
|
|
@ -164,8 +164,11 @@ public interface BootstrapContext {
|
||||||
* @apiNote Supported for internal use only. This method will go away as
|
* @apiNote Supported for internal use only. This method will go away as
|
||||||
* we migrate away from Hibernate Commons Annotations to Jandex for
|
* we migrate away from Hibernate Commons Annotations to Jandex for
|
||||||
* annotation handling and XMl to annotation merging.
|
* annotation handling and XMl to annotation merging.
|
||||||
|
*
|
||||||
|
* @deprecated HCANN is deprecated in favor of hibernate-models
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
|
@Deprecated
|
||||||
ReflectionManager getReflectionManager();
|
ReflectionManager getReflectionManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,18 +38,12 @@ public enum OptimisticLockStyle {
|
||||||
ALL;
|
ALL;
|
||||||
|
|
||||||
public static OptimisticLockStyle fromLockType(OptimisticLockType type) {
|
public static OptimisticLockStyle fromLockType(OptimisticLockType type) {
|
||||||
switch ( type ) {
|
return switch ( type ) {
|
||||||
case VERSION:
|
case VERSION -> VERSION;
|
||||||
return VERSION;
|
case NONE -> NONE;
|
||||||
case NONE:
|
case DIRTY -> DIRTY;
|
||||||
return NONE;
|
case ALL -> ALL;
|
||||||
case DIRTY:
|
};
|
||||||
return DIRTY;
|
|
||||||
case ALL:
|
|
||||||
return ALL;
|
|
||||||
default:
|
|
||||||
throw new AssertionFailure( "Unrecognized OptimisticLockType" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllOrDirty() {
|
public boolean isAllOrDirty() {
|
||||||
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
/*
|
||||||
|
* 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 java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.boot.models.categorize.spi.GlobalRegistrations;
|
||||||
|
import org.hibernate.boot.models.categorize.spi.JpaEventListener;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.jpa.event.spi.CallbackDefinition;
|
||||||
|
import org.hibernate.jpa.event.spi.CallbackType;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.models.spi.AnnotationUsage;
|
||||||
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.ClassDetailsRegistry;
|
||||||
|
import org.hibernate.models.spi.MethodDetails;
|
||||||
|
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||||
|
import org.hibernate.property.access.spi.Getter;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EntityListeners;
|
||||||
|
import jakarta.persistence.ExcludeDefaultListeners;
|
||||||
|
import jakarta.persistence.ExcludeSuperclassListeners;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import jakarta.persistence.PersistenceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves JPA callback definitions
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public final class CallbackDefinitionResolver {
|
||||||
|
private static final Logger log = Logger.getLogger( CallbackDefinitionResolver.class );
|
||||||
|
|
||||||
|
public static List<CallbackDefinition> resolveEntityCallbacks(
|
||||||
|
MetadataBuildingContext metadataBuildingContext,
|
||||||
|
ClassDetails entityClass,
|
||||||
|
CallbackType callbackType) {
|
||||||
|
final GlobalRegistrations globalRegistrations = metadataBuildingContext.getMetadataCollector().getGlobalRegistrations();
|
||||||
|
final List<JpaEventListener> globalListenerRegistrations = globalRegistrations.getEntityListenerRegistrations();
|
||||||
|
|
||||||
|
List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
|
||||||
|
List<String> callbacksMethodNames = new ArrayList<>();
|
||||||
|
List<ClassDetails> orderedListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
ClassDetails currentClazz = entityClass;
|
||||||
|
boolean stopListeners = false;
|
||||||
|
boolean stopDefaultListeners = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
CallbackDefinition callbackDefinition = null;
|
||||||
|
final List<MethodDetails> methodsDetailsList = currentClazz.getMethods();
|
||||||
|
for ( MethodDetails methodDetails : methodsDetailsList ) {
|
||||||
|
if ( !methodDetails.hasAnnotationUsage( callbackType.getCallbackAnnotation() ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( callbacksMethodNames.contains( methodDetails.getName() ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//overridden method, remove the superclass overridden method
|
||||||
|
if ( callbackDefinition == null ) {
|
||||||
|
final Method javaMethod = (Method) methodDetails.toJavaMember();
|
||||||
|
callbackDefinition = new EntityCallback.Definition( javaMethod, callbackType );
|
||||||
|
Class<?> returnType = javaMethod.getReturnType();
|
||||||
|
Class<?>[] args = javaMethod.getParameterTypes();
|
||||||
|
if ( returnType != Void.TYPE || args.length != 0 ) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Callback methods annotated on the bean class must return void and take no arguments: "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName() + " - " + methodDetails
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ReflectHelper.ensureAccessibility( javaMethod );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debugf(
|
||||||
|
"Adding %s as %s callback for entity %s",
|
||||||
|
methodDetails.getName(),
|
||||||
|
callbackType.getCallbackAnnotation().getSimpleName(),
|
||||||
|
entityClass.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
|
||||||
|
callbacksMethodNames.add( 0, methodDetails.getName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"You can only annotate one callback method with "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName() + " in bean class: " + entityClass.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !stopListeners ) {
|
||||||
|
applyListeners( currentClazz, orderedListeners );
|
||||||
|
stopListeners = currentClazz.hasAnnotationUsage( ExcludeSuperclassListeners.class );
|
||||||
|
stopDefaultListeners = currentClazz.hasAnnotationUsage( ExcludeDefaultListeners.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
currentClazz = currentClazz.getSuperClass();
|
||||||
|
}
|
||||||
|
while ( currentClazz != null
|
||||||
|
&& !( currentClazz.hasAnnotationUsage( Entity.class )
|
||||||
|
|| currentClazz.hasAnnotationUsage( MappedSuperclass.class ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
while ( currentClazz != null );
|
||||||
|
|
||||||
|
//handle default listeners
|
||||||
|
if ( !stopDefaultListeners ) {
|
||||||
|
if ( CollectionHelper.isNotEmpty( globalListenerRegistrations ) ) {
|
||||||
|
int defaultListenerSize = globalListenerRegistrations.size();
|
||||||
|
for ( int i = defaultListenerSize - 1; i >= 0; i-- ) {
|
||||||
|
orderedListeners.add( globalListenerRegistrations.get( i ).getCallbackClass() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ClassDetails listenerClassDetails : orderedListeners ) {
|
||||||
|
CallbackDefinition callbackDefinition = null;
|
||||||
|
if ( listenerClassDetails != null ) {
|
||||||
|
for ( MethodDetails methodDetails : listenerClassDetails.getMethods() ) {
|
||||||
|
if ( methodDetails.hasAnnotationUsage( callbackType.getCallbackAnnotation() ) ) {
|
||||||
|
final String methodName = methodDetails.getName();
|
||||||
|
//overridden method, remove the superclass overridden method
|
||||||
|
if ( callbackDefinition == null ) {
|
||||||
|
final Method method = (Method) methodDetails.toJavaMember();
|
||||||
|
callbackDefinition = new ListenerCallback.Definition(
|
||||||
|
listenerClassDetails.toJavaClass(),
|
||||||
|
method,
|
||||||
|
callbackType
|
||||||
|
);
|
||||||
|
|
||||||
|
final Class<?> returnType = method.getReturnType();
|
||||||
|
final Class<?>[] args = method.getParameterTypes();
|
||||||
|
if ( returnType != Void.TYPE || args.length != 1 ) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Callback methods annotated in a listener bean class must return void and take one argument: "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName() + " - " + methodDetails
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ReflectHelper.ensureAccessibility( method );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debugf(
|
||||||
|
"Adding %s as %s callback for entity %s",
|
||||||
|
methodName,
|
||||||
|
callbackType.getCallbackAnnotation().getSimpleName(),
|
||||||
|
entityClass.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
callbackDefinitions.add( 0, callbackDefinition ); // listeners first
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"You can only annotate one callback method with "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName()
|
||||||
|
+ " in bean class: " + entityClass.getName()
|
||||||
|
+ " and callback listener: " + listenerClassDetails.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callbackDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<CallbackDefinition> resolveEmbeddableCallbacks(
|
||||||
|
MetadataBuildingContext metadataBuildingContext,
|
||||||
|
Class<?> entityClass,
|
||||||
|
Property embeddableProperty,
|
||||||
|
CallbackType callbackType) {
|
||||||
|
final SourceModelBuildingContext hibernateModelsContext = metadataBuildingContext.getMetadataCollector().getSourceModelBuildingContext();
|
||||||
|
final ClassDetailsRegistry classDetailsRegistry = hibernateModelsContext.getClassDetailsRegistry();
|
||||||
|
|
||||||
|
final Class<?> embeddableClass = embeddableProperty.getType().getReturnedClass();
|
||||||
|
final ClassDetails embeddableClassDetails = classDetailsRegistry.getClassDetails( embeddableClass.getName() );
|
||||||
|
|
||||||
|
final Getter embeddableGetter = embeddableProperty.getGetter( entityClass );
|
||||||
|
final List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
|
||||||
|
final List<String> callbacksMethodNames = new ArrayList<>();
|
||||||
|
ClassDetails currentClazz = embeddableClassDetails;
|
||||||
|
do {
|
||||||
|
CallbackDefinition callbackDefinition = null;
|
||||||
|
final List<MethodDetails> methodsDetailsList = currentClazz.getMethods();
|
||||||
|
for ( MethodDetails methodDetails : methodsDetailsList ) {
|
||||||
|
if ( !methodDetails.hasAnnotationUsage( callbackType.getCallbackAnnotation() ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Method method = (Method) methodDetails.toJavaMember();
|
||||||
|
final String methodName = method.getName();
|
||||||
|
|
||||||
|
if ( callbacksMethodNames.contains( methodName ) ) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"You can only annotate one callback method with "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName() + " in bean class: " + currentClazz.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//overridden method, remove the superclass overridden method
|
||||||
|
if ( callbackDefinition == null ) {
|
||||||
|
callbackDefinition = new EmbeddableCallback.Definition( embeddableGetter, method, callbackType );
|
||||||
|
Class<?> returnType = method.getReturnType();
|
||||||
|
Class<?>[] args = method.getParameterTypes();
|
||||||
|
if ( returnType != Void.TYPE || args.length != 0 ) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Callback methods annotated on the bean class must return void and take no arguments: "
|
||||||
|
+ callbackType.getCallbackAnnotation().getName() + " - " + methodDetails
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ReflectHelper.ensureAccessibility( method );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debugf(
|
||||||
|
"Adding %s as %s callback for entity %s",
|
||||||
|
methodName,
|
||||||
|
callbackType.getCallbackAnnotation().getSimpleName(),
|
||||||
|
currentClazz.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
|
||||||
|
callbacksMethodNames.add( 0, methodName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
currentClazz = currentClazz.getSuperClass();
|
||||||
|
}
|
||||||
|
while ( currentClazz != null && !currentClazz.hasAnnotationUsage( MappedSuperclass.class ) );
|
||||||
|
}
|
||||||
|
while ( currentClazz != null );
|
||||||
|
|
||||||
|
return callbackDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean useAnnotationAnnotatedByListener;
|
||||||
|
|
||||||
|
static {
|
||||||
|
//check whether reading annotations of annotations is useful or not
|
||||||
|
useAnnotationAnnotatedByListener = false;
|
||||||
|
Target target = EntityListeners.class.getAnnotation( Target.class );
|
||||||
|
if ( target != null ) {
|
||||||
|
for ( ElementType type : target.value() ) {
|
||||||
|
if ( type.equals( ElementType.ANNOTATION_TYPE ) ) {
|
||||||
|
useAnnotationAnnotatedByListener = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyListeners(ClassDetails currentClazz, List<ClassDetails> listOfListeners) {
|
||||||
|
final AnnotationUsage<EntityListeners> entityListeners = currentClazz.getAnnotationUsage( EntityListeners.class );
|
||||||
|
if ( entityListeners != null ) {
|
||||||
|
final List<ClassDetails> listeners = entityListeners.getList( "value" );
|
||||||
|
listOfListeners.addAll( listeners );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( useAnnotationAnnotatedByListener ) {
|
||||||
|
final List<AnnotationUsage<?>> metaAnnotatedUsageList = currentClazz.getMetaAnnotated( EntityListeners.class );
|
||||||
|
for ( AnnotationUsage<?> metaAnnotatedUsage : metaAnnotatedUsageList ) {
|
||||||
|
final AnnotationUsage<EntityListeners> metaAnnotatedListeners = metaAnnotatedUsage.getAnnotationDescriptor().getAnnotationUsage( EntityListeners.class );
|
||||||
|
final List<ClassDetails> listeners = metaAnnotatedListeners.getList( "value" );
|
||||||
|
listOfListeners.addAll( listeners );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue