Enforce JPA/Hibernate initialization before context refresh completion
Closes gh-21868
This commit is contained in:
parent
c9e85ec297
commit
dedc6a7e9b
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2023 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -40,8 +40,10 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.context.ResourceLoaderAware;
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
|
import org.springframework.core.InfrastructureProxy;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
@ -79,7 +81,8 @@ import org.springframework.lang.Nullable;
|
||||||
* @see org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
|
* @see org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
|
||||||
*/
|
*/
|
||||||
public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
implements FactoryBean<SessionFactory>, ResourceLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
|
implements FactoryBean<SessionFactory>, ResourceLoaderAware, BeanFactoryAware,
|
||||||
|
InitializingBean, SmartInitializingSingleton, DisposableBean {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
@ -390,6 +393,8 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
* then block until Hibernate's bootstrapping completed, if not ready by then.
|
* then block until Hibernate's bootstrapping completed, if not ready by then.
|
||||||
* For maximum benefit, make sure to avoid early {@code SessionFactory} calls
|
* For maximum benefit, make sure to avoid early {@code SessionFactory} calls
|
||||||
* in init methods of related beans, even for metadata introspection purposes.
|
* in init methods of related beans, even for metadata introspection purposes.
|
||||||
|
* <p>As of 6.2, Hibernate initialization is enforced before context refresh
|
||||||
|
* completion, waiting for asynchronous bootstrapping to complete by then.
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
* @see LocalSessionFactoryBuilder#buildSessionFactory(AsyncTaskExecutor)
|
* @see LocalSessionFactoryBuilder#buildSessionFactory(AsyncTaskExecutor)
|
||||||
*/
|
*/
|
||||||
|
|
@ -600,6 +605,14 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
this.sessionFactory = buildSessionFactory(sfb);
|
this.sessionFactory = buildSessionFactory(sfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
// Enforce completion of asynchronous Hibernate initialization before context refresh completion.
|
||||||
|
if (this.sessionFactory instanceof InfrastructureProxy proxy) {
|
||||||
|
proxy.getWrappedObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses can override this method to perform custom initialization
|
* Subclasses can override this method to perform custom initialization
|
||||||
* of the SessionFactory instance, creating it via the given Configuration
|
* of the SessionFactory instance, creating it via the given Configuration
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ import org.springframework.beans.factory.BeanNameAware;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
import org.springframework.core.task.AsyncTaskExecutor;
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
|
|
@ -90,8 +91,9 @@ import org.springframework.util.CollectionUtils;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public abstract class AbstractEntityManagerFactoryBean implements
|
public abstract class AbstractEntityManagerFactoryBean implements
|
||||||
FactoryBean<EntityManagerFactory>, BeanClassLoaderAware, BeanFactoryAware, BeanNameAware,
|
FactoryBean<EntityManagerFactory>, BeanClassLoaderAware, BeanFactoryAware,
|
||||||
InitializingBean, DisposableBean, EntityManagerFactoryInfo, PersistenceExceptionTranslator, Serializable {
|
BeanNameAware, InitializingBean, SmartInitializingSingleton, DisposableBean,
|
||||||
|
EntityManagerFactoryInfo, PersistenceExceptionTranslator, Serializable {
|
||||||
|
|
||||||
/** Logger available to subclasses. */
|
/** Logger available to subclasses. */
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
@ -318,6 +320,8 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||||
* then block until the JPA provider's bootstrapping completed, if not ready by then.
|
* then block until the JPA provider's bootstrapping completed, if not ready by then.
|
||||||
* For maximum benefit, make sure to avoid early {@code EntityManagerFactory} calls
|
* For maximum benefit, make sure to avoid early {@code EntityManagerFactory} calls
|
||||||
* in init methods of related beans, even for metadata introspection purposes.
|
* in init methods of related beans, even for metadata introspection purposes.
|
||||||
|
* <p>As of 6.2, JPA initialization is enforced before context refresh completion,
|
||||||
|
* waiting for asynchronous bootstrapping to complete by then.
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public void setBootstrapExecutor(@Nullable AsyncTaskExecutor bootstrapExecutor) {
|
public void setBootstrapExecutor(@Nullable AsyncTaskExecutor bootstrapExecutor) {
|
||||||
|
|
@ -403,6 +407,12 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
||||||
this.entityManagerFactory = createEntityManagerFactoryProxy(this.nativeEntityManagerFactory);
|
this.entityManagerFactory = createEntityManagerFactoryProxy(this.nativeEntityManagerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
// Enforce completion of asynchronous JPA initialization before context refresh completion.
|
||||||
|
getNativeEntityManagerFactory();
|
||||||
|
}
|
||||||
|
|
||||||
private EntityManagerFactory buildNativeEntityManagerFactory() {
|
private EntityManagerFactory buildNativeEntityManagerFactory() {
|
||||||
EntityManagerFactory emf;
|
EntityManagerFactory emf;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="hibernateStatistics" factory-bean="entityManagerFactory" factory-method="getStatistics"/>
|
<bean id="hibernateStatistics" factory-bean="entityManagerFactory" factory-method="getStatistics" lazy-init="true"/>
|
||||||
|
|
||||||
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
|
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<bean id="dao" class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceUnitSetterNamedPerson"/>
|
<bean id="dao" class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceUnitSetterNamedPerson"/>
|
||||||
|
|
||||||
<bean class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceContextSetter"/>
|
<bean class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceContextSetter" lazy-init="true"/>
|
||||||
|
|
||||||
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
|
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
|
||||||
<property name="proxyTargetClass" value="true"/>
|
<property name="proxyTargetClass" value="true"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue