Commit d39a8360 authored by Oliver Gierke's avatar Oliver Gierke

Added support to allow manually declaring a EntityManagerFactoryBean.

Added the necessary @ConditionalOnMissingBean annotations to allow selectively declaring an EntityManagerFactoryBean, a JpaVendorAdapter or a PlatformTransactionManager. Especially the first one might be necessary to make sure the persistence provider evaluates an orm.xml. This unfortunately rules out using the packages to scan feature of Spring's LCEMFB.

I've filed https://jira.springsource.org/browse/SPR-11260 to potentially remove the need for this workaround in Spring itself.
parent 88d4d8d7
......@@ -34,6 +34,7 @@ import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
......@@ -51,6 +52,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
*
* @author Phillip Webb
* @author Dave Syer
* @author Oliver Gierke
*/
public abstract class JpaBaseConfiguration implements BeanFactoryAware, EnvironmentAware {
......@@ -64,14 +66,16 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware, Environm
}
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
return new JpaTransactionManager();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
@ConditionalOnMissingBean(EntityManagerFactoryInfo.class)
public LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerFactoryBean.setDataSource(getDataSource());
entityManagerFactoryBean.setPackagesToScan(getPackagesToScan());
entityManagerFactoryBean.getJpaPropertyMap().putAll(
......@@ -81,6 +85,7 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware, Environm
}
@Bean
@ConditionalOnMissingBean(JpaVendorAdapter.class)
public JpaVendorAdapter jpaVendorAdapter() {
AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
adapter.setShowSql(this.environment.getProperty("show-sql", Boolean.class, true));
......
......@@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.orm.jpa;
import java.util.Collections;
import java.util.Map;
import javax.sql.DataSource;
......@@ -27,6 +28,7 @@ import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.AbstractJpaAutoConfigurationTests.TestConfigurationWithTransactionManager.CustomJpaTransactionManager;
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
......@@ -34,11 +36,14 @@ 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 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.web.context.support.AnnotationConfigWebApplicationContext;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
......@@ -130,9 +135,35 @@ public abstract class AbstractJpaAutoConfigurationTests {
assertThat(map.get("a"), equalTo((Object) "b"));
assertThat(map.get("c"), equalTo((Object) "d"));
}
@Test
public void usesManuallyDefinedEntityManagerFactoryBeanIfAvailable() {
setupTestConfiguration(TestConfigurationWithEntityManagerFactory.class);
this.context.refresh();
LocalContainerEntityManagerFactoryBean factoryBean = this.context.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = factoryBean.getJpaPropertyMap();
assertThat(map.get("configured"), is((Object) "manually"));
}
@Test
public void usesManuallyDefinedTransactionManagerBeanIfAvailable() {
setupTestConfiguration(TestConfigurationWithTransactionManager.class);
this.context.refresh();
PlatformTransactionManager txManager = this.context.getBean(PlatformTransactionManager.class);
assertThat(txManager, is(instanceOf(CustomJpaTransactionManager.class)));
}
protected void setupTestConfiguration() {
this.context.register(TestConfiguration.class,
setupTestConfiguration(TestConfiguration.class);
}
protected void setupTestConfiguration(Class<?> configClass) {
this.context.register(configClass,
ComponentScanDetectorConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
......@@ -156,7 +187,34 @@ public abstract class AbstractJpaAutoConfigurationTests {
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
return new OpenEntityManagerInViewFilter();
}
}
@Configuration
protected static class TestConfigurationWithEntityManagerFactory extends TestConfiguration {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter adapter) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setJpaVendorAdapter(adapter);
factoryBean.setDataSource(dataSource);
factoryBean.setPersistenceUnitName("manually-configured");
factoryBean.setJpaPropertyMap(Collections.singletonMap("configured", "manually"));
return factoryBean;
}
}
@Configuration
@ComponentScan(basePackageClasses = { City.class })
protected static class TestConfigurationWithTransactionManager {
@Bean
public PlatformTransactionManager transactionManager() {
return new CustomJpaTransactionManager();
}
static class CustomJpaTransactionManager extends JpaTransactionManager {
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="manually-configured">
<class>org.springframework.boot.autoconfigure.orm.jpa.test.City</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment