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 97161871387..89472a6359b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,17 @@ package org.springframework.orm.jpa; +import java.util.Collections; + +import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.util.ClassUtils; /** - * {@link RuntimeHintsRegistrar} implementation that makes sure JDK proxy hints related to - * {@link AbstractEntityManagerFactoryBean} are registered. + * {@link RuntimeHintsRegistrar} implementation that makes sure that hints related to + * {@link AbstractEntityManagerFactoryBean} and {@link SharedEntityManagerCreator} are registered. * * @author Sebastien Deleuze * @since 6.0 @@ -32,6 +35,8 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar { private static final String HIBERNATE_SESSION_FACTORY_CLASS_NAME = "org.hibernate.SessionFactory"; + private static final String ENTITY_MANAGER_FACTORY_CLASS_NAME = "jakarta.persistence.EntityManagerFactory"; + @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { if (ClassUtils.isPresent(HIBERNATE_SESSION_FACTORY_CLASS_NAME, classLoader)) { @@ -40,5 +45,13 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar { hints.proxies().registerJdkProxy(TypeReference.of("org.hibernate.Session"), TypeReference.of(EntityManagerProxy.class)); } + if (ClassUtils.isPresent(ENTITY_MANAGER_FACTORY_CLASS_NAME, classLoader)) { + hints.reflection().registerType(TypeReference.of(ENTITY_MANAGER_FACTORY_CLASS_NAME), builder -> { + builder.onReachableType(SharedEntityManagerCreator.class).withMethod("getCriteriaBuilder", + Collections.emptyList(), ExecutableMode.INVOKE); + builder.onReachableType(SharedEntityManagerCreator.class).withMethod("getMetamodel", + Collections.emptyList(), ExecutableMode.INVOKE); + }); + } } } 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 b14c3e4db5b..5b43a20dcd0 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.orm.jpa; +import jakarta.persistence.EntityManagerFactory; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.jupiter.api.BeforeEach; @@ -56,4 +57,10 @@ class EntityManagerRuntimeHintsTests { assertThat(RuntimeHintsPredicates.proxies().forInterfaces(Session.class, EntityManagerProxy.class)) .accepts(this.hints); } + + @Test + void entityManagerFactoryHasReflectionHints() { + assertThat(RuntimeHintsPredicates.reflection().onMethod(EntityManagerFactory.class, "getCriteriaBuilder")).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(EntityManagerFactory.class, "getMetamodel")).accepts(this.hints); + } }