diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerRuntimeHints.java b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerRuntimeHints.java index 5ab9fee6ad6..f836e0911b3 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerRuntimeHints.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerRuntimeHints.java @@ -21,6 +21,7 @@ import java.util.Collections; import org.jspecify.annotations.Nullable; import org.springframework.aot.hint.ExecutableMode; +import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; @@ -54,6 +55,10 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar { private static final String NATIVE_QUERY_IMPL_CLASS_NAME = "org.hibernate.query.sql.internal.NativeQueryImpl"; + private static final String STATELESS_SESSION_CLASS_NAME = "org.hibernate.StatelessSession"; + + private static final String PERSISTENCE_UNIT_INFO_DESCRIPTOR_CLASS_NAME = + "org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor"; @Override public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { @@ -71,32 +76,21 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar { Collections.emptyList(), ExecutableMode.INVOKE); }); } + registerJdkProxyFor(hints, classLoader, QUERY_SQM_IMPL_CLASS_NAME); + registerJdkProxyFor(hints, classLoader, SQM_QUERY_IMPL_CLASS_NAME); + registerJdkProxyFor(hints, classLoader, SELECTION_QUERY_IMPL_CLASS_NAME); + registerJdkProxyFor(hints, classLoader, MUTATION_QUERY_IMPL_CLASS_NAME); + registerJdkProxyFor(hints, classLoader, NATIVE_QUERY_IMPL_CLASS_NAME); + registerJdkProxyFor(hints, classLoader, STATELESS_SESSION_CLASS_NAME); + if (ClassUtils.isPresent(PERSISTENCE_UNIT_INFO_DESCRIPTOR_CLASS_NAME, classLoader)) { + hints.reflection().registerType(TypeReference.of(PERSISTENCE_UNIT_INFO_DESCRIPTOR_CLASS_NAME), + MemberCategory.INVOKE_PUBLIC_METHODS); + } + } + + private static void registerJdkProxyFor(RuntimeHints hints, @Nullable ClassLoader classLoader, String className) { try { - Class clazz = ClassUtils.forName(QUERY_SQM_IMPL_CLASS_NAME, classLoader); - hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader)); - } - catch (ClassNotFoundException ignored) { - } - try { - Class clazz = ClassUtils.forName(SQM_QUERY_IMPL_CLASS_NAME, classLoader); - hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader)); - } - catch (ClassNotFoundException ignored) { - } - try { - Class clazz = ClassUtils.forName(SELECTION_QUERY_IMPL_CLASS_NAME, classLoader); - hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader)); - } - catch (ClassNotFoundException ignored) { - } - try { - Class clazz = ClassUtils.forName(MUTATION_QUERY_IMPL_CLASS_NAME, classLoader); - hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader)); - } - catch (ClassNotFoundException ignored) { - } - try { - Class clazz = ClassUtils.forName(NATIVE_QUERY_IMPL_CLASS_NAME, classLoader); + Class clazz = ClassUtils.forName(className, classLoader); hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader)); } catch (ClassNotFoundException ignored) { diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java index 917722e8d01..57df0615ef8 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java @@ -19,6 +19,8 @@ package org.springframework.orm.jpa; import jakarta.persistence.EntityManagerFactory; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -55,6 +57,7 @@ class EntityManagerRuntimeHintsTests { void entityManagerProxyHasHibernateHints() { assertThat(RuntimeHintsPredicates.proxies().forInterfaces(Session.class, EntityManagerProxy.class)) .accepts(this.hints); + assertThat(RuntimeHintsPredicates.proxies().forInterfaces(StatelessSession.class)).accepts(this.hints); } @Test @@ -63,4 +66,10 @@ class EntityManagerRuntimeHintsTests { assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(EntityManagerFactory.class, "getMetamodel")).accepts(this.hints); } + @Test + void persistenceUnitInfoDescriptorHasReflectionHints() { + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(PersistenceUnitInfoDescriptor.class, "getName")) + .accepts(this.hints); + } + }