mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Merge branch '7.0.x'
This commit is contained in:
+52
-30
@@ -1075,25 +1075,25 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
* if not recovered yet, and at debug level if already recovered.
|
||||
* Can be overridden in subclasses.
|
||||
* @param ex the exception to handle
|
||||
* @param alreadyRecovered whether a previously executing listener
|
||||
* already recovered from the present listener setup failure
|
||||
* (this usually indicates a follow-up failure than can be ignored
|
||||
* other than for debug log purposes)
|
||||
* @param alreadyHandled whether a previously executing listener already
|
||||
* recovered from the present listener setup failure or the problem has
|
||||
* been handled otherwise already (this usually indicates a follow-up
|
||||
* failure than can be ignored other than for debug log purposes)
|
||||
* @see #recoverAfterListenerSetupFailure()
|
||||
*/
|
||||
protected void handleListenerSetupFailure(Throwable ex, boolean alreadyRecovered) {
|
||||
protected void handleListenerSetupFailure(Throwable ex, boolean alreadyHandled) {
|
||||
if (ex instanceof JMSException jmsException) {
|
||||
invokeExceptionListener(jmsException);
|
||||
}
|
||||
if (ex instanceof SharedConnectionNotInitializedException) {
|
||||
if (!alreadyRecovered) {
|
||||
if (!alreadyHandled) {
|
||||
logger.debug("JMS message listener invoker needs to establish shared Connection");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Recovery during active operation...
|
||||
if (alreadyRecovered) {
|
||||
logger.debug("Setup of JMS message listener invoker failed - already recovered by other invoker", ex);
|
||||
if (alreadyHandled) {
|
||||
logger.debug("Setup of JMS message listener invoker failed", ex);
|
||||
}
|
||||
else {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
@@ -1317,6 +1317,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
lifecycleLock.unlock();
|
||||
}
|
||||
boolean messageReceived = false;
|
||||
boolean exhausted = false;
|
||||
try {
|
||||
// For core consumers without maxMessagesPerTask, no idle limit applies since they
|
||||
// will always get rescheduled immediately anyway. Whereas for surplus consumers
|
||||
@@ -1340,31 +1341,45 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
clearResources();
|
||||
boolean alreadyHandled = false;
|
||||
if (this.invokerBackOff != null) {
|
||||
// We failed more than once in a row, probably due to a specific failure
|
||||
// from the JMS receive call even after a successful connection recovery:
|
||||
// locally wait before a further recovery attempt to avoid a burst retry.
|
||||
applyBackOffTime(this.invokerBackOff);
|
||||
alreadyHandled = true;
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Recurring setup failure in " + id() + " - retrying using " +
|
||||
this.invokerBackOff + ". Cause: " + (ex instanceof JMSException jmsException ?
|
||||
JmsUtils.buildExceptionMessage(jmsException) : ex.getMessage()));
|
||||
}
|
||||
exhausted = !applyBackOffTime(this.invokerBackOff);
|
||||
if (exhausted) {
|
||||
// Too many recurring setup failures at the invoker level.
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Exhausted back-off in " + id() + " after recurring setup failure: " +
|
||||
this.invokerBackOff);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.invokerBackOff = DefaultMessageListenerContainer.this.backOff.start();
|
||||
}
|
||||
boolean alreadyRecovered = false;
|
||||
recoveryLock.lock();
|
||||
try {
|
||||
if (this.lastRecoveryMarker == currentRecoveryMarker) {
|
||||
handleListenerSetupFailure(ex, false);
|
||||
recoverAfterListenerSetupFailure();
|
||||
currentRecoveryMarker = new Object();
|
||||
boolean recovered = false;
|
||||
if (!exhausted) {
|
||||
recoveryLock.lock();
|
||||
try {
|
||||
if (this.lastRecoveryMarker == DefaultMessageListenerContainer.this.currentRecoveryMarker) {
|
||||
handleListenerSetupFailure(ex, alreadyHandled);
|
||||
recoverAfterListenerSetupFailure();
|
||||
DefaultMessageListenerContainer.this.currentRecoveryMarker = new Object();
|
||||
recovered = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
alreadyRecovered = true;
|
||||
finally {
|
||||
recoveryLock.unlock();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
recoveryLock.unlock();
|
||||
}
|
||||
if (alreadyRecovered) {
|
||||
if (!recovered) {
|
||||
handleListenerSetupFailure(ex, true);
|
||||
}
|
||||
}
|
||||
@@ -1385,7 +1400,8 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
}
|
||||
lifecycleLock.lock();
|
||||
try {
|
||||
if (!shouldRescheduleInvoker(this.idleTaskExecutionCount) || !rescheduleTaskIfNecessary(this)) {
|
||||
if (exhausted || !shouldRescheduleInvoker(this.idleTaskExecutionCount) ||
|
||||
!rescheduleTaskIfNecessary(this)) {
|
||||
// We're shutting down completely.
|
||||
scheduledInvokers.remove(this);
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -1394,16 +1410,15 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
lifecycleCondition.signalAll();
|
||||
clearResources();
|
||||
}
|
||||
else if (isRunning()) {
|
||||
if (isRunning()) {
|
||||
int nonPausedConsumers = getScheduledConsumerCount() - getPausedTaskCount();
|
||||
if (nonPausedConsumers < 1) {
|
||||
logger.error("All scheduled consumers have been paused, probably due to tasks having been rejected. " +
|
||||
"Check your thread pool configuration! Manual recovery necessary through a start() call.");
|
||||
logger.error("All scheduled consumers have been paused due to tasks having been exhausted/rejected. " +
|
||||
"Check your back-off and executor setup! Manual recovery necessary through a start() call.");
|
||||
}
|
||||
else if (nonPausedConsumers < getConcurrentConsumers()) {
|
||||
logger.warn("Number of scheduled consumers has dropped below concurrentConsumers limit, probably " +
|
||||
"due to tasks having been rejected. Check your thread pool configuration! Automatic recovery " +
|
||||
"to be triggered by remaining consumers.");
|
||||
logger.warn("Number of scheduled consumers has dropped below concurrentConsumers limit due to tasks " +
|
||||
"having been exhausted/rejected. Automatic recovery to be triggered by remaining consumers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1461,7 +1476,10 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
try {
|
||||
initResourcesIfNecessary();
|
||||
boolean messageReceived = receiveAndExecute(this, this.session, this.consumer);
|
||||
this.invokerBackOff = null; // successful receive attempt without exception
|
||||
if (this.invokerBackOff != null) {
|
||||
logger.debug("Successful receive attempt after JMS message listener invoker recovery");
|
||||
this.invokerBackOff = null;
|
||||
}
|
||||
return messageReceived;
|
||||
}
|
||||
finally {
|
||||
@@ -1552,6 +1570,10 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
this.session = null;
|
||||
}
|
||||
|
||||
private String id() {
|
||||
return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongLived() {
|
||||
return (maxMessagesPerTask < 0);
|
||||
|
||||
+6
-6
@@ -513,6 +513,7 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||
* Delegate an incoming invocation from the proxy, dispatching to EntityManagerFactoryInfo
|
||||
* or the native EntityManagerFactory accordingly.
|
||||
*/
|
||||
@SuppressWarnings("NullAway") // for query.unwrap(null)
|
||||
Object invokeProxyMethod(Method method, Object @Nullable [] args) throws Throwable {
|
||||
if (method.getDeclaringClass().isAssignableFrom(EntityManagerFactoryInfo.class)) {
|
||||
return method.invoke(this, args);
|
||||
@@ -521,9 +522,8 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||
args[0] == SynchronizationType.SYNCHRONIZED) {
|
||||
// JPA 2.1's createEntityManager(SynchronizationType, Map)
|
||||
// Redirect to plain createEntityManager and add synchronization semantics through Spring proxy
|
||||
EntityManager rawEntityManager = (args.length > 1 ?
|
||||
getNativeEntityManagerFactory().createEntityManager((Map<?, ?>) args[1]) :
|
||||
getNativeEntityManagerFactory().createEntityManager());
|
||||
EntityManager rawEntityManager = EntityManagerFactoryUtils.createEntityManager(
|
||||
getNativeEntityManagerFactory(), (args.length > 1 ? (Map<?, ?>) args[1] : null));
|
||||
postProcessEntityManager(rawEntityManager);
|
||||
return ExtendedEntityManagerCreator.createApplicationManagedEntityManager(rawEntityManager, this, true);
|
||||
}
|
||||
@@ -536,6 +536,7 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||
// Assumably a Spring-generated proxy from SharedEntityManagerCreator:
|
||||
// since we're passing it back to the native EntityManagerFactory,
|
||||
// let's unwrap it to the original Query object from the provider.
|
||||
// Note that null is not an officially supported argument in JPA.
|
||||
try {
|
||||
args[i] = query.unwrap(null);
|
||||
}
|
||||
@@ -609,9 +610,8 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||
|
||||
@Override
|
||||
public EntityManager createNativeEntityManager(@Nullable Map<?, ?> properties) {
|
||||
EntityManager rawEntityManager = (!CollectionUtils.isEmpty(properties) ?
|
||||
getNativeEntityManagerFactory().createEntityManager(properties) :
|
||||
getNativeEntityManagerFactory().createEntityManager());
|
||||
EntityManager rawEntityManager = EntityManagerFactoryUtils.createEntityManager(
|
||||
getNativeEntityManagerFactory(), properties);
|
||||
postProcessEntityManager(rawEntityManager);
|
||||
return rawEntityManager;
|
||||
}
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ public abstract class EntityManagerFactoryAccessor implements BeanFactoryAware {
|
||||
protected EntityManager createEntityManager() throws IllegalStateException {
|
||||
EntityManagerFactory emf = obtainEntityManagerFactory();
|
||||
Map<String, Object> properties = getJpaPropertyMap();
|
||||
return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
|
||||
return EntityManagerFactoryUtils.createEntityManager(emf, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+26
-8
@@ -79,10 +79,10 @@ public abstract class EntityManagerFactoryUtils {
|
||||
public static final int ENTITY_MANAGER_SYNCHRONIZATION_ORDER =
|
||||
DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
|
||||
|
||||
private static final @Nullable Method CREATE_ENTITY_AGENT_METHOD =
|
||||
ClassUtils.getMethodIfAvailable(EntityManagerFactory.class, "createEntityAgent");
|
||||
private static final boolean CREATE_ENTITY_MANAGER_WITHOUT_ARGUMENTS_AVAILABLE =
|
||||
ClassUtils.hasMethod(EntityManagerFactory.class, "createEntityManager");
|
||||
|
||||
private static final @Nullable Method CREATE_ENTITY_AGENT_WITH_PROPERTIES_METHOD =
|
||||
private static final @Nullable Method CREATE_ENTITY_AGENT_METHOD =
|
||||
ClassUtils.getMethodIfAvailable(EntityManagerFactory.class, "createEntityAgent", Map.class);
|
||||
|
||||
private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class);
|
||||
@@ -268,7 +268,7 @@ public abstract class EntityManagerFactoryUtils {
|
||||
}
|
||||
}
|
||||
if (em == null) {
|
||||
em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
|
||||
em = createEntityManager(emf, properties);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -358,6 +358,23 @@ public abstract class EntityManagerFactoryUtils {
|
||||
return entityAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JPA EntityManager via reflectively detected JPA 3.2/4.0 API.
|
||||
* @param emf the EntityManagerFactory to create the EntityManager with
|
||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||
* call (may be {@code null})
|
||||
* @since 7.0.8
|
||||
*/
|
||||
public static EntityManager createEntityManager(EntityManagerFactory emf, @Nullable Map<?, ?> properties) {
|
||||
if (CollectionUtils.isEmpty(properties)) {
|
||||
properties = null;
|
||||
}
|
||||
if (properties == null && CREATE_ENTITY_MANAGER_WITHOUT_ARGUMENTS_AVAILABLE) {
|
||||
return emf.createEntityManager(); // on JPA 3.2
|
||||
}
|
||||
return emf.createEntityManager(properties); // on JPA 4.0 even for empty properties
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JPA EntityAgent via reflectively detected JPA 4.0 API.
|
||||
* @param emf the EntityManagerFactory to create the EntityAgent with
|
||||
@@ -366,12 +383,13 @@ public abstract class EntityManagerFactoryUtils {
|
||||
* @since 7.0.4
|
||||
*/
|
||||
static Object createEntityAgent(EntityManagerFactory emf, @Nullable Map<?, ?> properties) {
|
||||
if (CREATE_ENTITY_AGENT_METHOD == null || CREATE_ENTITY_AGENT_WITH_PROPERTIES_METHOD == null) {
|
||||
if (CREATE_ENTITY_AGENT_METHOD == null) {
|
||||
throw new IllegalStateException("JPA 4.0 createEntityAgent API not available");
|
||||
}
|
||||
Object entityAgent = (!CollectionUtils.isEmpty(properties) ?
|
||||
ReflectionUtils.invokeMethod(CREATE_ENTITY_AGENT_WITH_PROPERTIES_METHOD, emf, properties) :
|
||||
ReflectionUtils.invokeMethod(CREATE_ENTITY_AGENT_METHOD, emf));
|
||||
if (CollectionUtils.isEmpty(properties)) {
|
||||
properties = null;
|
||||
}
|
||||
Object entityAgent = ReflectionUtils.invokeMethod(CREATE_ENTITY_AGENT_METHOD, emf, properties);
|
||||
if (entityAgent == null) {
|
||||
throw new IllegalStateException("JPA 4.0 createEntityAgent API returned null");
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.util.ClassUtils;
|
||||
* {@link AbstractEntityManagerFactoryBean} and {@link SharedEntityManagerCreator} are registered.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Juergen Hoeller
|
||||
* @since 6.0
|
||||
*/
|
||||
class EntityManagerRuntimeHints implements RuntimeHintsRegistrar {
|
||||
@@ -45,6 +46,12 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar {
|
||||
// As of Hibernate 7.1
|
||||
private static final String SQM_QUERY_IMPL_CLASS_NAME = "org.hibernate.query.sqm.internal.SqmQueryImpl";
|
||||
|
||||
// As of Hibernate 8.0
|
||||
private static final String SELECTION_QUERY_IMPL_CLASS_NAME = "org.hibernate.query.internal.SelectionQueryImpl";
|
||||
|
||||
// As of Hibernate 8.0
|
||||
private static final String MUTATION_QUERY_IMPL_CLASS_NAME = "org.hibernate.query.internal.MutationQueryImpl";
|
||||
|
||||
private static final String NATIVE_QUERY_IMPL_CLASS_NAME = "org.hibernate.query.sql.internal.NativeQueryImpl";
|
||||
|
||||
|
||||
@@ -76,6 +83,18 @@ class EntityManagerRuntimeHints implements RuntimeHintsRegistrar {
|
||||
}
|
||||
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);
|
||||
hints.proxies().registerJdkProxy(ClassUtils.getAllInterfacesForClass(clazz, classLoader));
|
||||
|
||||
+1
-3
@@ -42,7 +42,6 @@ import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
|
||||
/**
|
||||
@@ -174,8 +173,7 @@ public abstract class ExtendedEntityManagerCreator {
|
||||
return createProxy(rawEntityManager, emfInfo, true, synchronizedWithTransaction);
|
||||
}
|
||||
else {
|
||||
EntityManager rawEntityManager = (!CollectionUtils.isEmpty(properties) ?
|
||||
emf.createEntityManager(properties) : emf.createEntityManager());
|
||||
EntityManager rawEntityManager = EntityManagerFactoryUtils.createEntityManager(emf, properties);
|
||||
return createProxy(rawEntityManager, null, null, null, null, true, synchronizedWithTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,8 +475,7 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager
|
||||
em = emfInfo.createNativeEntityManager(properties);
|
||||
}
|
||||
else {
|
||||
em = (!CollectionUtils.isEmpty(properties) ?
|
||||
emf.createEntityManager(properties) : emf.createEntityManager());
|
||||
em = EntityManagerFactoryUtils.createEntityManager(emf, properties);
|
||||
}
|
||||
if (this.entityManagerInitializer != null) {
|
||||
this.entityManagerInitializer.accept(em);
|
||||
|
||||
+9
-5
@@ -143,9 +143,7 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
*/
|
||||
public PersistenceConfiguration getPersistenceConfiguration() {
|
||||
if (this.configuration == null) {
|
||||
String name = getPersistenceUnitName();
|
||||
Assert.state(name != null, "No persistenceUnitName set");
|
||||
this.configuration = new PersistenceConfiguration(name);
|
||||
this.configuration = new PersistenceConfiguration(obtainPersistenceUnitName());
|
||||
}
|
||||
return this.configuration;
|
||||
}
|
||||
@@ -167,6 +165,12 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
super.setPersistenceUnitName(persistenceUnitName);
|
||||
}
|
||||
|
||||
private String obtainPersistenceUnitName() {
|
||||
String name = getPersistenceUnitName();
|
||||
Assert.state(name != null, "No persistenceUnitName set");
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use Spring-based scanning for entity classes in the classpath
|
||||
* instead of using JPA's standard scanning of jar files with {@code persistence.xml}
|
||||
@@ -265,7 +269,7 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
// Create EntityManagerFactory directly through PersistenceProvider.
|
||||
EntityManagerFactory emf = (this.configuration != null ?
|
||||
provider.createEntityManagerFactory(this.configuration) :
|
||||
provider.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap()));
|
||||
provider.createEntityManagerFactory(obtainPersistenceUnitName(), getJpaPropertyMap()));
|
||||
if (emf == null) {
|
||||
throw new PersistenceException(
|
||||
"PersistenceProvider [" + provider + "] could not find persistence unit for name '" +
|
||||
@@ -277,7 +281,7 @@ public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryB
|
||||
// Let JPA perform its standard PersistenceProvider autodetection.
|
||||
return (this.configuration != null ?
|
||||
Persistence.createEntityManagerFactory(this.configuration) :
|
||||
Persistence.createEntityManagerFactory(getPersistenceUnitName(), getJpaPropertyMap()));
|
||||
Persistence.createEntityManagerFactory(obtainPersistenceUnitName(), getJpaPropertyMap()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -40,7 +40,6 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
|
||||
/**
|
||||
@@ -396,9 +395,7 @@ public abstract class SharedEntityManagerCreator {
|
||||
boolean newTarget = false;
|
||||
if (target == null) {
|
||||
logger.debug("Creating new EntityManager for shared EntityManager invocation");
|
||||
target = (!CollectionUtils.isEmpty(this.properties) ?
|
||||
this.targetFactory.createEntityManager(this.properties) :
|
||||
this.targetFactory.createEntityManager());
|
||||
target = EntityManagerFactoryUtils.createEntityManager(this.targetFactory, this.properties);
|
||||
newTarget = true;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -146,7 +146,11 @@ public final class PersistenceManagedTypesScanner {
|
||||
try {
|
||||
MetadataReader reader = factory.getMetadataReader(resource);
|
||||
String className = reader.getClassMetadata().getClassName();
|
||||
if (matchesEntityTypeFilter(reader, factory) && this.managedClassNameFilter.matches(className)) {
|
||||
if (className.endsWith(ClassUtils.PACKAGE_INFO_SUFFIX)) {
|
||||
scanResult.managedPackages.add(className.substring(0,
|
||||
className.length() - ClassUtils.PACKAGE_INFO_SUFFIX.length()));
|
||||
}
|
||||
else if (matchesEntityTypeFilter(reader, factory) && this.managedClassNameFilter.matches(className)) {
|
||||
scanResult.managedClassNames.add(className);
|
||||
if (scanResult.persistenceUnitRootUrl == null) {
|
||||
URL url = resource.getURL();
|
||||
@@ -155,10 +159,6 @@ public final class PersistenceManagedTypesScanner {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (className.endsWith(ClassUtils.PACKAGE_INFO_SUFFIX)) {
|
||||
scanResult.managedPackages.add(className.substring(0,
|
||||
className.length() - ClassUtils.PACKAGE_INFO_SUFFIX.length()));
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
// Ignore non-readable resource
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
|
||||
* @see jakarta.persistence.EntityManagerFactory#createEntityManager()
|
||||
*/
|
||||
protected EntityManager createEntityManager(EntityManagerFactory emf) {
|
||||
return emf.createEntityManager();
|
||||
return EntityManagerFactoryUtils.createEntityManager(emf, null);
|
||||
}
|
||||
|
||||
private boolean applyEntityManagerBindingInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
|
||||
+1
-16
@@ -19,11 +19,6 @@ package org.springframework.orm.jpa;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.query.CommonQueryContract;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
import org.hibernate.query.hql.spi.SqmQueryImplementor;
|
||||
import org.hibernate.query.spi.DomainQueryExecutionContext;
|
||||
import org.hibernate.query.sqm.spi.InterpretationsKeySource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -47,8 +42,7 @@ class EntityManagerRuntimeHintsTests {
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
AotServices.factories().load(RuntimeHintsRegistrar.class)
|
||||
.forEach(registrar -> registrar.registerHints(this.hints,
|
||||
ClassUtils.getDefaultClassLoader()));
|
||||
.forEach(registrar -> registrar.registerHints(this.hints, ClassUtils.getDefaultClassLoader()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,13 +63,4 @@ class EntityManagerRuntimeHintsTests {
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(EntityManagerFactory.class, "getMetamodel")).accepts(this.hints);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sqmQueryHints() {
|
||||
assertThat(RuntimeHintsPredicates.proxies().forInterfaces(
|
||||
SqmQueryImplementor.class,
|
||||
InterpretationsKeySource.class,
|
||||
DomainQueryExecutionContext.class,
|
||||
SelectionQuery.class,
|
||||
CommonQueryContract.class)).accepts(this.hints);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -76,19 +76,20 @@ class OpenEntityManagerInViewTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
void setup() {
|
||||
given(factory.createEntityManager()).willReturn(manager);
|
||||
this.request.setAsyncSupported(true);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
void cleanup() {
|
||||
assertThat(TransactionSynchronizationManager.getResourceMap()).isEmpty();
|
||||
assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse();
|
||||
assertThat(TransactionSynchronizationManager.isCurrentTransactionReadOnly()).isFalse();
|
||||
assertThat(TransactionSynchronizationManager.isActualTransactionActive()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void openEntityManagerInViewInterceptor() {
|
||||
OpenEntityManagerInViewInterceptor interceptor = new OpenEntityManagerInViewInterceptor();
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ class PersistenceContextTransactionTests {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clear() {
|
||||
void cleanup() {
|
||||
assertThat(TransactionSynchronizationManager.getResourceMap()).isEmpty();
|
||||
assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse();
|
||||
assertThat(TransactionSynchronizationManager.isCurrentTransactionReadOnly()).isFalse();
|
||||
|
||||
Reference in New Issue
Block a user