Skip to content

Commit 4030090

Browse files
committed
Include vendor properties in auto-configured EntityManagerFactoryBuilder
This commit moves the setup of vendor properties (e.g. Hibernate) from the auto-configured LocalContainerEntityManagerFactoryBean to the auto-configured EntityManagerFactoryBuilder. This way, custom use of the latter retains additional auto-configuration logic such as the naming strategy and DDL mode to use. Closes gh-15318
1 parent 4eebb8e commit 4030090

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

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

Lines changed: 11 additions & 5 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.HashMap;
1920
import java.util.List;
2021
import java.util.Map;
2122

@@ -119,22 +120,27 @@ public JpaVendorAdapter jpaVendorAdapter() {
119120
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
120121
ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
121122
ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
122-
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
123-
this.properties.getProperties(), persistenceUnitManager.getIfAvailable());
123+
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter, buildJpaProperties(),
124+
persistenceUnitManager.getIfAvailable());
124125
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
125126
return builder;
126127
}
127128

129+
private Map<String, ?> buildJpaProperties() {
130+
Map<String, Object> properties = new HashMap<>(this.properties.getProperties());
131+
Map<String, Object> vendorProperties = getVendorProperties();
132+
customizeVendorProperties(vendorProperties);
133+
properties.putAll(vendorProperties);
134+
return properties;
135+
}
136+
128137
@Bean
129138
@Primary
130139
@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })
131140
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder,
132141
PersistenceManagedTypes persistenceManagedTypes) {
133-
Map<String, Object> vendorProperties = getVendorProperties();
134-
customizeVendorProperties(vendorProperties);
135142
return factoryBuilder.dataSource(this.dataSource)
136143
.managedTypes(persistenceManagedTypes)
137-
.properties(vendorProperties)
138144
.mappingResources(getMappingResources())
139145
.jta(isJta())
140146
.build();

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
4242
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration;
4343
import org.springframework.boot.jdbc.DataSourceBuilder;
44+
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
4445
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
4546
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4647
import org.springframework.boot.test.context.runner.ContextConsumer;
@@ -207,6 +208,18 @@ void customJpaProperties() {
207208
});
208209
}
209210

211+
@Test
212+
void usesManuallyDefinedLocalContainerEntityManagerFactoryBeanUsingBuilder() {
213+
this.contextRunner.withPropertyValues("spring.jpa.properties.a=b")
214+
.withUserConfiguration(TestConfigurationWithEntityManagerFactoryBuilder.class)
215+
.run((context) -> {
216+
LocalContainerEntityManagerFactoryBean factoryBean = context
217+
.getBean(LocalContainerEntityManagerFactoryBean.class);
218+
Map<String, Object> map = factoryBean.getJpaPropertyMap();
219+
assertThat(map).containsEntry("configured", "manually").containsEntry("a", "b");
220+
});
221+
}
222+
210223
@Test
211224
void usesManuallyDefinedLocalContainerEntityManagerFactoryBeanIfAvailable() {
212225
this.contextRunner.withUserConfiguration(TestConfigurationWithLocalContainerEntityManagerFactoryBean.class)
@@ -380,6 +393,17 @@ static class ManualOpenEntityManagerInViewInterceptor extends OpenEntityManagerI
380393

381394
}
382395

396+
@Configuration(proxyBeanMethods = false)
397+
static class TestConfigurationWithEntityManagerFactoryBuilder extends TestConfiguration {
398+
399+
@Bean
400+
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder,
401+
DataSource dataSource) {
402+
return builder.dataSource(dataSource).properties(Map.of("configured", "manually")).build();
403+
}
404+
405+
}
406+
383407
@Configuration(proxyBeanMethods = false)
384408
static class TestConfigurationWithLocalContainerEntityManagerFactoryBean extends TestConfiguration {
385409

spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-access.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ It scans entities located in the same package as `Order`.
311311
It is possible to map additional JPA properties using the `app.first.jpa` namespace.
312312

313313
NOTE: When you create a bean for `LocalContainerEntityManagerFactoryBean` yourself, any customization that was applied during the creation of the auto-configured `LocalContainerEntityManagerFactoryBean` is lost.
314-
For example, in the case of Hibernate, any properties under the `spring.jpa.hibernate` prefix will not be automatically applied to your `LocalContainerEntityManagerFactoryBean`.
315-
If you were relying on these properties for configuring things like the naming strategy or the DDL mode, you will need to explicitly configure that when creating the `LocalContainerEntityManagerFactoryBean` bean.
314+
Make sure to use the auto-configured `EntityManagerFactoryBuilder` to retain JPA and vendor properties.
315+
This is particularly important if you were relying on `spring.jpa.*` properties for configuring things like the naming strategy or the DDL mode.
316316

317317
You should provide a similar configuration for any additional data sources for which you need JPA access.
318318
To complete the picture, you need to configure a `JpaTransactionManager` for each `EntityManagerFactory` as well.

0 commit comments

Comments
 (0)