Skip to content

Commit cf3c2a0

Browse files
committed
Merge pull request #47802 from Asanio06
* pr/47802: Polish contribution Add support for configuring additional PersistenceUnitPostProcessor Closes gh-47802
2 parents ab28e5e + 9602be2 commit cf3c2a0

File tree

4 files changed

+158
-4
lines changed

4 files changed

+158
-4
lines changed

module/spring-boot-hibernate/src/test/java/org/springframework/boot/hibernate/autoconfigure/HibernateJpaAutoConfigurationTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,19 @@ void customPersistenceUnitPostProcessors() {
351351
});
352352
}
353353

354+
@Test
355+
void customPersistenceUnitProcessorsAddedByServeralContributors() {
356+
this.contextRunner.withUserConfiguration(TestConfigurationWithMultipleCustomPersistenceUnitPostProcessors.class)
357+
.run((context) -> {
358+
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = context
359+
.getBean(LocalContainerEntityManagerFactoryBean.class);
360+
PersistenceUnitInfo persistenceUnitInfo = entityManagerFactoryBean.getPersistenceUnitInfo();
361+
assertThat(persistenceUnitInfo).isNotNull();
362+
assertThat(persistenceUnitInfo.getManagedClassNames()).contains(
363+
"customized.attribute.converter.class.name", "customized.attribute.converter.class.anotherName");
364+
});
365+
}
366+
354367
@Test
355368
void customManagedClassNameFilter() {
356369
this.contextRunner.withBean(ManagedClassNameFilter.class, () -> (s) -> !s.endsWith("City"))
@@ -1168,6 +1181,24 @@ EntityManagerFactoryBuilderCustomizer entityManagerFactoryBuilderCustomizer() {
11681181

11691182
}
11701183

1184+
@Configuration(proxyBeanMethods = false)
1185+
@TestAutoConfigurationPackage(HibernateJpaAutoConfigurationTests.class)
1186+
static class TestConfigurationWithMultipleCustomPersistenceUnitPostProcessors {
1187+
1188+
@Bean
1189+
EntityManagerFactoryBuilderCustomizer entityManagerFactoryBuilderCustomizer() {
1190+
return (builder) -> builder.addPersistenceUnitPostProcessors(
1191+
(pui) -> pui.addManagedClassName("customized.attribute.converter.class.name"));
1192+
}
1193+
1194+
@Bean
1195+
EntityManagerFactoryBuilderCustomizer anotherEntityManagerFactoryBuilderCustomizer() {
1196+
return (builder) -> builder.addPersistenceUnitPostProcessors(
1197+
(pui) -> pui.addManagedClassName("customized.attribute.converter.class.anotherName"));
1198+
}
1199+
1200+
}
1201+
11711202
static class CustomJpaTransactionManager extends JpaTransactionManager {
11721203

11731204
}

module/spring-boot-jpa/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ dependencies {
3636
testImplementation(project(":core:spring-boot-test"))
3737
testImplementation(project(":test-support:spring-boot-test-support"))
3838
testImplementation(testFixtures(project(":core:spring-boot-autoconfigure")))
39-
testImplementation("org.springframework:spring-context-support")
4039
}
4140

4241
tasks.named("compileTestJava") {

module/spring-boot-jpa/src/main/java/org/springframework/boot/jpa/EntityManagerFactoryBuilder.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
package org.springframework.boot.jpa;
1818

1919
import java.net.URL;
20+
import java.util.ArrayList;
21+
import java.util.Arrays;
2022
import java.util.HashMap;
2123
import java.util.HashSet;
2224
import java.util.LinkedHashMap;
25+
import java.util.List;
2326
import java.util.Map;
2427
import java.util.Set;
2528
import java.util.function.Function;
@@ -63,7 +66,7 @@ public class EntityManagerFactoryBuilder {
6366

6467
private @Nullable AsyncTaskExecutor bootstrapExecutor;
6568

66-
private PersistenceUnitPostProcessor @Nullable [] persistenceUnitPostProcessors;
69+
private @Nullable List<PersistenceUnitPostProcessor> persistenceUnitPostProcessors;
6770

6871
/**
6972
* Create a new instance passing in the common pieces that will be shared if multiple
@@ -126,7 +129,23 @@ public void setBootstrapExecutor(AsyncTaskExecutor bootstrapExecutor) {
126129
* @param persistenceUnitPostProcessors the persistence unit post processors to use
127130
*/
128131
public void setPersistenceUnitPostProcessors(PersistenceUnitPostProcessor... persistenceUnitPostProcessors) {
129-
this.persistenceUnitPostProcessors = persistenceUnitPostProcessors;
132+
this.persistenceUnitPostProcessors = new ArrayList<>(Arrays.asList(persistenceUnitPostProcessors));
133+
}
134+
135+
/**
136+
* Add {@linkplain PersistenceUnitPostProcessor persistence unit post processors} to
137+
* be applied to the PersistenceUnitInfo used for creating the
138+
* {@link LocalContainerEntityManagerFactoryBean}.
139+
* @param persistenceUnitPostProcessors the persistence unit post processors to add
140+
* @since 4.1.0
141+
*/
142+
public void addPersistenceUnitPostProcessors(PersistenceUnitPostProcessor... persistenceUnitPostProcessors) {
143+
if (this.persistenceUnitPostProcessors != null) {
144+
this.persistenceUnitPostProcessors.addAll(Arrays.asList(persistenceUnitPostProcessors));
145+
}
146+
else {
147+
setPersistenceUnitPostProcessors(persistenceUnitPostProcessors);
148+
}
130149
}
131150

132151
/**
@@ -280,7 +299,8 @@ else if (this.packagesToScan != null) {
280299
}
281300
if (EntityManagerFactoryBuilder.this.persistenceUnitPostProcessors != null) {
282301
entityManagerFactoryBean
283-
.setPersistenceUnitPostProcessors(EntityManagerFactoryBuilder.this.persistenceUnitPostProcessors);
302+
.setPersistenceUnitPostProcessors(EntityManagerFactoryBuilder.this.persistenceUnitPostProcessors
303+
.toArray(PersistenceUnitPostProcessor[]::new));
284304
}
285305
return entityManagerFactoryBean;
286306
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.jpa;
18+
19+
import java.util.Collections;
20+
import java.util.Map;
21+
import java.util.function.Function;
22+
23+
import javax.sql.DataSource;
24+
25+
import jakarta.persistence.spi.PersistenceProvider;
26+
import org.assertj.core.api.InstanceOfAssertFactories;
27+
import org.junit.jupiter.api.Test;
28+
29+
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
30+
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.mockito.Mockito.mock;
34+
35+
/**
36+
* Tests for {@link EntityManagerFactoryBuilder}.
37+
*
38+
* @author Stephane Nicoll
39+
*/
40+
class EntityManagerFactoryBuilderTests {
41+
42+
@Test
43+
void setPersistenceUnitPostProcessorsWhenEmpty() {
44+
EntityManagerFactoryBuilder builder = createEmptyBuilder();
45+
PersistenceUnitPostProcessor postProcessor = mock();
46+
PersistenceUnitPostProcessor postProcessor2 = mock();
47+
builder.setPersistenceUnitPostProcessors(postProcessor, postProcessor2);
48+
assertThat(builder).extracting("persistenceUnitPostProcessors")
49+
.asInstanceOf(InstanceOfAssertFactories.LIST)
50+
.containsExactly(postProcessor, postProcessor2);
51+
}
52+
53+
@Test
54+
void addPersistenceUnitPostProcessorsWhenEmpty() {
55+
EntityManagerFactoryBuilder builder = createEmptyBuilder();
56+
PersistenceUnitPostProcessor postProcessor = mock();
57+
PersistenceUnitPostProcessor postProcessor2 = mock();
58+
builder.addPersistenceUnitPostProcessors(postProcessor, postProcessor2);
59+
assertThat(builder).extracting("persistenceUnitPostProcessors")
60+
.asInstanceOf(InstanceOfAssertFactories.LIST)
61+
.containsExactly(postProcessor, postProcessor2);
62+
}
63+
64+
@Test
65+
void setPersistenceUnitPostProcessorsWhenNotEmpty() {
66+
EntityManagerFactoryBuilder builder = createEmptyBuilder();
67+
PersistenceUnitPostProcessor postProcessor = mock();
68+
builder.addPersistenceUnitPostProcessors(postProcessor);
69+
PersistenceUnitPostProcessor postProcessor2 = mock();
70+
PersistenceUnitPostProcessor postProcessor3 = mock();
71+
builder.setPersistenceUnitPostProcessors(postProcessor2, postProcessor3);
72+
assertThat(builder).extracting("persistenceUnitPostProcessors")
73+
.asInstanceOf(InstanceOfAssertFactories.LIST)
74+
.containsExactly(postProcessor2, postProcessor3);
75+
}
76+
77+
@Test
78+
void addPersistenceUnitPostProcessorsWhenNotEmpty() {
79+
EntityManagerFactoryBuilder builder = createEmptyBuilder();
80+
PersistenceUnitPostProcessor postProcessor = mock();
81+
builder.addPersistenceUnitPostProcessors(postProcessor);
82+
PersistenceUnitPostProcessor postProcessor2 = mock();
83+
builder.addPersistenceUnitPostProcessors(postProcessor2);
84+
assertThat(builder).extracting("persistenceUnitPostProcessors")
85+
.asInstanceOf(InstanceOfAssertFactories.LIST)
86+
.containsExactly(postProcessor, postProcessor2);
87+
}
88+
89+
private EntityManagerFactoryBuilder createEmptyBuilder() {
90+
Function<DataSource, Map<String, ?>> jpaPropertiesFactory = (dataSource) -> Collections
91+
.emptyMap();
92+
return new EntityManagerFactoryBuilder(new TestJpaVendorAdapter(), jpaPropertiesFactory, null);
93+
}
94+
95+
static class TestJpaVendorAdapter extends AbstractJpaVendorAdapter {
96+
97+
@Override
98+
public PersistenceProvider getPersistenceProvider() {
99+
return mock();
100+
}
101+
102+
}
103+
104+
}

0 commit comments

Comments
 (0)