Skip to content

Commit d39a836

Browse files
committed
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.
1 parent 88d4d8d commit d39a836

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.context.annotation.Bean;
3535
import org.springframework.context.annotation.Configuration;
3636
import org.springframework.core.env.Environment;
37+
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
3738
import org.springframework.orm.jpa.JpaTransactionManager;
3839
import org.springframework.orm.jpa.JpaVendorAdapter;
3940
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
@@ -51,6 +52,7 @@
5152
*
5253
* @author Phillip Webb
5354
* @author Dave Syer
55+
* @author Oliver Gierke
5456
*/
5557
public abstract class JpaBaseConfiguration implements BeanFactoryAware, EnvironmentAware {
5658

@@ -64,14 +66,16 @@ public void setEnvironment(Environment environment) {
6466
}
6567

6668
@Bean
69+
@ConditionalOnMissingBean(PlatformTransactionManager.class)
6770
public PlatformTransactionManager transactionManager() {
68-
return new JpaTransactionManager(entityManagerFactory().getObject());
71+
return new JpaTransactionManager();
6972
}
7073

7174
@Bean
72-
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
75+
@ConditionalOnMissingBean(EntityManagerFactoryInfo.class)
76+
public LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter jpaVendorAdapter) {
7377
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
74-
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
78+
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
7579
entityManagerFactoryBean.setDataSource(getDataSource());
7680
entityManagerFactoryBean.setPackagesToScan(getPackagesToScan());
7781
entityManagerFactoryBean.getJpaPropertyMap().putAll(
@@ -81,6 +85,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
8185
}
8286

8387
@Bean
88+
@ConditionalOnMissingBean(JpaVendorAdapter.class)
8489
public JpaVendorAdapter jpaVendorAdapter() {
8590
AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
8691
adapter.setShowSql(this.environment.getProperty("show-sql", Boolean.class, true));

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/AbstractJpaAutoConfigurationTests.java

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.autoconfigure.orm.jpa;
1818

19+
import java.util.Collections;
1920
import java.util.Map;
2021

2122
import javax.sql.DataSource;
@@ -27,18 +28,22 @@
2728
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
2829
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
2930
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
31+
import org.springframework.boot.autoconfigure.orm.jpa.AbstractJpaAutoConfigurationTests.TestConfigurationWithTransactionManager.CustomJpaTransactionManager;
3032
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
3133
import org.springframework.context.ApplicationContext;
3234
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3335
import org.springframework.context.annotation.Bean;
3436
import org.springframework.context.annotation.ComponentScan;
3537
import org.springframework.context.annotation.Configuration;
3638
import org.springframework.orm.jpa.JpaTransactionManager;
39+
import org.springframework.orm.jpa.JpaVendorAdapter;
3740
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
3841
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
3942
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
43+
import org.springframework.transaction.PlatformTransactionManager;
4044
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
4145

46+
import static org.hamcrest.CoreMatchers.*;
4247
import static org.hamcrest.Matchers.equalTo;
4348
import static org.junit.Assert.assertEquals;
4449
import static org.junit.Assert.assertNotNull;
@@ -130,9 +135,35 @@ public void customJpaProperties() throws Exception {
130135
assertThat(map.get("a"), equalTo((Object) "b"));
131136
assertThat(map.get("c"), equalTo((Object) "d"));
132137
}
138+
139+
@Test
140+
public void usesManuallyDefinedEntityManagerFactoryBeanIfAvailable() {
141+
142+
setupTestConfiguration(TestConfigurationWithEntityManagerFactory.class);
143+
this.context.refresh();
144+
145+
LocalContainerEntityManagerFactoryBean factoryBean = this.context.getBean(LocalContainerEntityManagerFactoryBean.class);
146+
Map<String, Object> map = factoryBean.getJpaPropertyMap();
147+
assertThat(map.get("configured"), is((Object) "manually"));
148+
}
149+
150+
@Test
151+
public void usesManuallyDefinedTransactionManagerBeanIfAvailable() {
152+
153+
setupTestConfiguration(TestConfigurationWithTransactionManager.class);
154+
this.context.refresh();
155+
156+
PlatformTransactionManager txManager = this.context.getBean(PlatformTransactionManager.class);
157+
assertThat(txManager, is(instanceOf(CustomJpaTransactionManager.class)));
158+
}
133159

134160
protected void setupTestConfiguration() {
135-
this.context.register(TestConfiguration.class,
161+
setupTestConfiguration(TestConfiguration.class);
162+
}
163+
164+
protected void setupTestConfiguration(Class<?> configClass) {
165+
166+
this.context.register(configClass,
136167
ComponentScanDetectorConfiguration.class,
137168
EmbeddedDataSourceConfiguration.class,
138169
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
@@ -156,7 +187,34 @@ protected static class TestFilterConfiguration {
156187
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
157188
return new OpenEntityManagerInViewFilter();
158189
}
159-
160190
}
161-
191+
192+
@Configuration
193+
protected static class TestConfigurationWithEntityManagerFactory extends TestConfiguration {
194+
195+
@Bean
196+
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter adapter) {
197+
198+
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
199+
factoryBean.setJpaVendorAdapter(adapter);
200+
factoryBean.setDataSource(dataSource);
201+
factoryBean.setPersistenceUnitName("manually-configured");
202+
factoryBean.setJpaPropertyMap(Collections.singletonMap("configured", "manually"));
203+
return factoryBean;
204+
}
205+
}
206+
207+
@Configuration
208+
@ComponentScan(basePackageClasses = { City.class })
209+
protected static class TestConfigurationWithTransactionManager {
210+
211+
@Bean
212+
public PlatformTransactionManager transactionManager() {
213+
return new CustomJpaTransactionManager();
214+
}
215+
216+
static class CustomJpaTransactionManager extends JpaTransactionManager {
217+
218+
}
219+
}
162220
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<persistence-unit name="manually-configured">
4+
<class>org.springframework.boot.autoconfigure.orm.jpa.test.City</class>
5+
<exclude-unlisted-classes>true</exclude-unlisted-classes>
6+
</persistence-unit>
7+
</persistence>

0 commit comments

Comments
 (0)