Browse Source

Register Hibernate `@EmbeddableInstantiator` reflection hints

This commit updates PersistenceManagedTypesBeanRegistrationAotProcessor
to register reflection hints for `@EmbeddableInstantiator` annotations
available as of Hibernate 6.0 when needed.

Related tests will be added in
https://github.com/spring-projects/spring-aot-smoke-tests.

Closes gh-31534
pull/31571/head
Sébastien Deleuze 11 months ago
parent
commit
9d6bda2b44
  1. 35
      spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java

35
spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java

@ -23,6 +23,7 @@ import javax.lang.model.element.Modifier;
import jakarta.persistence.Convert; import jakarta.persistence.Convert;
import jakarta.persistence.Converter; import jakarta.persistence.Converter;
import jakarta.persistence.Embedded;
import jakarta.persistence.EntityListeners; import jakarta.persistence.EntityListeners;
import jakarta.persistence.IdClass; import jakarta.persistence.IdClass;
import jakarta.persistence.PostLoad; import jakarta.persistence.PostLoad;
@ -64,11 +65,26 @@ import org.springframework.util.ReflectionUtils;
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 6.0 * @since 6.0
*/ */
@SuppressWarnings("unchecked")
class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class, private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class,
PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class); PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class);
@Nullable
private static Class<? extends Annotation> embeddableInstantiatorClass;
static {
try {
embeddableInstantiatorClass = (Class<? extends Annotation>) ClassUtils.forName("org.hibernate.annotations.EmbeddableInstantiator",
PersistenceManagedTypesBeanRegistrationAotProcessor.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
embeddableInstantiatorClass = null;
}
}
@Nullable @Nullable
@Override @Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
@ -129,6 +145,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
contributeIdClassHints(hints, managedClass); contributeIdClassHints(hints, managedClass);
contributeConverterHints(hints, managedClass); contributeConverterHints(hints, managedClass);
contributeCallbackHints(hints, managedClass); contributeCallbackHints(hints, managedClass);
contributeHibernateHints(hints, managedClass);
} }
catch (ClassNotFoundException ex) { catch (ClassNotFoundException ex) {
throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex); throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex);
@ -176,5 +193,23 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
reflection.registerMethod(method, ExecutableMode.INVOKE), reflection.registerMethod(method, ExecutableMode.INVOKE),
method -> CALLBACK_TYPES.stream().anyMatch(method::isAnnotationPresent)); method -> CALLBACK_TYPES.stream().anyMatch(method::isAnnotationPresent));
} }
@SuppressWarnings("unchecked")
private void contributeHibernateHints(RuntimeHints hints, Class<?> managedClass) {
if (embeddableInstantiatorClass == null) {
return;
}
ReflectionHints reflection = hints.reflection();
ReflectionUtils.doWithFields(managedClass, field -> {
Embedded embeddedAnnotation = AnnotationUtils.findAnnotation(field, Embedded.class);
if (embeddedAnnotation != null && field.getAnnotatedType().getType() instanceof Class<?> embeddedClass) {
Annotation embeddableInstantiatorAnnotation = AnnotationUtils.findAnnotation(embeddedClass, embeddableInstantiatorClass);
if (embeddableInstantiatorAnnotation != null) {
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(embeddableInstantiatorAnnotation).get("value");
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
}
});
}
} }
} }

Loading…
Cancel
Save