mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
[bs-178] Use OpenEntityManagerInView by default in webapp with JPA
If JPA is used and the context is a webapp we add the OEMIV interceptor. It can be switched off by the user declaring a bean of type OEMSIVI or the corresponding Filter, or by setting spring.jpa.open_in_view=false. [Fixes #52939983]
This commit is contained in:
parent
5b2986d7a9
commit
6dbd6d7c4c
@ -118,5 +118,10 @@
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -41,7 +41,7 @@ import org.springframework.util.StringUtils;
|
||||
@Configuration
|
||||
@ConditionalOnClass(HibernateEntityManager.class)
|
||||
@EnableTransactionManagement
|
||||
public class HibernateJpaAutoConfiguration extends JpaAutoConfiguration {
|
||||
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DIALECTS;
|
||||
static {
|
||||
|
@ -32,23 +32,32 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.bootstrap.context.condition.ConditionalOnBean;
|
||||
import org.springframework.bootstrap.context.condition.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.condition.ConditionalOnExpression;
|
||||
import org.springframework.bootstrap.context.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Base {@link EnableAutoConfiguration Auto-configuration} for JPA.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class,
|
||||
EnableTransactionManagement.class, EntityManager.class })
|
||||
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EnableTransactionManagement.class,
|
||||
EntityManager.class })
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
public abstract class JpaAutoConfiguration implements BeanFactoryAware {
|
||||
public abstract class JpaBaseConfiguration implements BeanFactoryAware {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
@ -67,19 +76,33 @@ public abstract class JpaAutoConfiguration implements BeanFactoryAware {
|
||||
return entityManagerFactoryBean;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class, OpenEntityManagerInViewFilter.class })
|
||||
@ConditionalOnExpression("${spring.jpa.openInView:${spring.jpa.open_in_view:true}}")
|
||||
protected static class JpaWebConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
super.addInterceptors(registry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() {
|
||||
return new OpenEntityManagerInViewInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the {@code dataSource} being used by Spring was created from
|
||||
* {@link EmbeddedDatabaseConfiguration}.
|
||||
* Determines if the {@code dataSource} being used by Spring was created from {@link EmbeddedDatabaseConfiguration}.
|
||||
* @return true if the data source was auto-configured.
|
||||
*/
|
||||
protected boolean isAutoConfiguredDataSource() {
|
||||
try {
|
||||
BeanDefinition beanDefinition = this.beanFactory
|
||||
.getBeanDefinition("dataSource");
|
||||
return EmbeddedDatabaseConfiguration.class.getName().equals(
|
||||
beanDefinition.getFactoryBeanName());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("dataSource");
|
||||
return EmbeddedDatabaseConfiguration.class.getName().equals(beanDefinition.getFactoryBeanName());
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -90,23 +113,19 @@ public abstract class JpaAutoConfiguration implements BeanFactoryAware {
|
||||
protected DataSource getDataSource() {
|
||||
try {
|
||||
return this.beanFactory.getBean("dataSource", DataSource.class);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
} catch (RuntimeException ex) {
|
||||
return this.beanFactory.getBean(DataSource.class);
|
||||
}
|
||||
}
|
||||
|
||||
protected String[] getPackagesToScan() {
|
||||
List<String> basePackages = AutoConfigurationUtils
|
||||
.getBasePackages(this.beanFactory);
|
||||
Assert.notEmpty(basePackages,
|
||||
"Unable to find JPA packages to scan, please define "
|
||||
+ "a @ComponentScan annotation or disable JpaAutoConfiguration");
|
||||
List<String> basePackages = AutoConfigurationUtils.getBasePackages(this.beanFactory);
|
||||
Assert.notEmpty(basePackages, "Unable to find JPA packages to scan, please define "
|
||||
+ "a @ComponentScan annotation or disable JpaAutoConfiguration");
|
||||
return basePackages.toArray(new String[basePackages.size()]);
|
||||
}
|
||||
|
||||
protected void configure(
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
|
||||
protected void configure(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
|
||||
}
|
||||
|
||||
@Override
|
@ -16,21 +16,29 @@
|
||||
|
||||
package org.springframework.autoconfigure.orm.jpa;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.autoconfigure.ComponentScanDetectorConfiguration;
|
||||
import org.springframework.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.autoconfigure.jdbc.EmbeddedDatabaseConfiguration;
|
||||
import org.springframework.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.autoconfigure.orm.jpa.test.City;
|
||||
import org.springframework.bootstrap.TestUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
/**
|
||||
* Tests for {@link HibernateJpaAutoConfiguration}.
|
||||
@ -39,11 +47,18 @@ import static org.junit.Assert.assertTrue;
|
||||
*/
|
||||
public class HibernateJpaAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityManagerCreated() throws Exception {
|
||||
this.context.register(ComponentScanDetectorConfiguration.class,
|
||||
((AnnotationConfigApplicationContext) this.context).register(ComponentScanDetectorConfiguration.class,
|
||||
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
@ -53,17 +68,58 @@ public class HibernateJpaAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testDataSourceTransactionManagerNotCreated() throws Exception {
|
||||
this.context.register(ComponentScanDetectorConfiguration.class,
|
||||
((AnnotationConfigApplicationContext) this.context).register(ComponentScanDetectorConfiguration.class,
|
||||
EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
|
||||
DataSourceTransactionManagerAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertNotNull(this.context.getBean(DataSource.class));
|
||||
assertTrue(this.context.getBean("transactionManager") instanceof JpaTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenEntityManagerInViewInterceptorCreated() throws Exception {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
TestConfiguration.class);
|
||||
this.context = context;
|
||||
this.context.refresh();
|
||||
assertNotNull(this.context.getBean(OpenEntityManagerInViewInterceptor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent() throws Exception {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(TestFilterConfiguration.class, ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context = context;
|
||||
this.context.refresh();
|
||||
assertEquals(0, this.context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff() throws Exception {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
TestUtils.addEnviroment(context, "spring.jpa.open_in_view:false");
|
||||
context.register(TestConfiguration.class, ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context = context;
|
||||
this.context.refresh();
|
||||
assertEquals(0, this.context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class).length);
|
||||
}
|
||||
|
||||
@ComponentScan(basePackageClasses = { City.class })
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ComponentScan(basePackageClasses = { City.class })
|
||||
@Configuration
|
||||
protected static class TestFilterConfiguration {
|
||||
@Bean
|
||||
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
|
||||
return new OpenEntityManagerInViewFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,11 @@
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
Loading…
Reference in New Issue
Block a user