Skip to content

Commit c2f649d

Browse files
committed
Add support for JPA mapping resources
Closes gh-10684
1 parent c402680 commit c2f649d

File tree

8 files changed

+127
-1
lines changed

8 files changed

+127
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory(
130130
Map<String, Object> vendorProperties = getVendorProperties();
131131
customizeVendorProperties(vendorProperties);
132132
return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan())
133-
.properties(vendorProperties).jta(isJta()).build();
133+
.properties(vendorProperties).mappingResources(getMappingResources())
134+
.jta(isJta()).build();
134135
}
135136

136137
protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
@@ -158,6 +159,11 @@ protected String[] getPackagesToScan() {
158159
return packages.toArray(new String[packages.size()]);
159160
}
160161

162+
private String[] getMappingResources() {
163+
List<String> mappingResources = this.properties.getMappingResources();
164+
return mappingResources.toArray(new String[mappingResources.size()]);
165+
}
166+
161167
/**
162168
* Return the JTA transaction manager.
163169
* @return the transaction manager or {@code null}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

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

19+
import java.util.ArrayList;
1920
import java.util.HashMap;
21+
import java.util.List;
2022
import java.util.Map;
2123

2224
import javax.sql.DataSource;
@@ -43,6 +45,11 @@ public class JpaProperties {
4345
*/
4446
private Map<String, String> properties = new HashMap<>();
4547

48+
/**
49+
* Mapping resources (equivalent to "mapping-file" entries in persistence.xml).
50+
*/
51+
private final List<String> mappingResources = new ArrayList<>();
52+
4653
/**
4754
* Name of the target database to operate on, auto-detected by default. Can be
4855
* alternatively set using the "Database" enum.
@@ -75,6 +82,10 @@ public void setProperties(Map<String, String> properties) {
7582
this.properties = properties;
7683
}
7784

85+
public List<String> getMappingResources() {
86+
return this.mappingResources;
87+
}
88+
7889
public String getDatabasePlatform() {
7990
return this.databasePlatform;
8091
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
4646
import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration;
4747
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
48+
import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity;
4849
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
4950
import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
5051
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
@@ -255,6 +256,22 @@ public void providerDisablesAutoCommitIsNotConfiguredWihJta() {
255256
});
256257
}
257258

259+
@Test
260+
public void customResourceMapping() {
261+
contextRunner()
262+
.withClassLoader(new HideDataScriptClassLoader())
263+
.withPropertyValues(
264+
"spring.datasource.data:classpath:/db/non-annotated-data.sql",
265+
"spring.jpa.mapping-resources=META-INF/mappings/non-annotated.xml")
266+
.run((context) -> {
267+
EntityManager em = context.getBean(EntityManagerFactory.class)
268+
.createEntityManager();
269+
NonAnnotatedEntity found = em.find(NonAnnotatedEntity.class, 2000L);
270+
assertThat(found).isNotNull();
271+
assertThat(found.getValue()).isEqualTo("Test");
272+
});
273+
}
274+
258275
@Configuration
259276
@TestAutoConfigurationPackage(City.class)
260277
static class TestInitializedJpaConfiguration {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2012-2017 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+
* http://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.autoconfigure.orm.jpa.mapping;
18+
19+
/**
20+
* A non annotated entity that is handled by a custom "mapping-file".
21+
*
22+
* @author Stephane Nicoll
23+
*/
24+
public class NonAnnotatedEntity {
25+
26+
private Long id;
27+
28+
private String value;
29+
30+
protected NonAnnotatedEntity() {
31+
}
32+
33+
public NonAnnotatedEntity(String value) {
34+
this.value = value;
35+
}
36+
37+
public Long getId() {
38+
return this.id;
39+
}
40+
41+
public void setId(Long id) {
42+
this.id = id;
43+
}
44+
45+
public String getValue() {
46+
return this.value;
47+
}
48+
49+
public void setValue(String value) {
50+
this.value = value;
51+
}
52+
53+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
5+
version="2.1">
6+
<entity class="org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity">
7+
<table name="NON_ANNOTATED"/>
8+
<attributes>
9+
<id name="id">
10+
<column name="id"/>
11+
<generated-value strategy="IDENTITY"/>
12+
</id>
13+
<basic name="value">
14+
<column name="value"/>
15+
</basic>
16+
</attributes>
17+
</entity>
18+
</entity-mappings>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
INSERT INTO NON_ANNOTATED (ID, VALUE) values (2000, 'Test');

spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ content into your application; rather pick only the properties that you need.
714714
spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name.
715715
spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name.
716716
spring.jpa.hibernate.use-new-id-generator-mappings= # Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.
717+
spring.jpa.mapping-resources= # Mapping resources (equivalent to "mapping-file" entries in persistence.xml).
717718
spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.
718719
spring.jpa.properties.*= # Additional native properties to set on the JPA provider.
719720
spring.jpa.show-sql=false # Enable logging of SQL statements.

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ public final class Builder {
113113

114114
private Map<String, Object> properties = new HashMap<>();
115115

116+
private String[] mappingResources;
117+
116118
private boolean jta;
117119

118120
private Builder(DataSource dataSource) {
@@ -166,6 +168,20 @@ public Builder properties(Map<String, ?> properties) {
166168
return this;
167169
}
168170

171+
/**
172+
* The mapping resources (equivalent to {@code <mapping-file>} entries in
173+
* {@code persistence.xml}) for the persistence unit.
174+
* <p>Note that mapping resources must be relative to the classpath root,
175+
* e.g. "META-INF/mappings.xml" or "com/mycompany/repository/mappings.xml",
176+
* so that they can be loaded through {@code ClassLoader.getResource}.
177+
* @param mappingResources the mapping resources to use
178+
* @return the builder for fluent usage
179+
*/
180+
public Builder mappingResources(String... mappingResources) {
181+
this.mappingResources = mappingResources;
182+
return this;
183+
}
184+
169185
/**
170186
* Configure if using a JTA {@link DataSource}, i.e. if
171187
* {@link LocalContainerEntityManagerFactoryBean#setDataSource(DataSource)
@@ -203,6 +219,9 @@ public LocalContainerEntityManagerFactoryBean build() {
203219
entityManagerFactoryBean.getJpaPropertyMap()
204220
.putAll(EntityManagerFactoryBuilder.this.jpaProperties);
205221
entityManagerFactoryBean.getJpaPropertyMap().putAll(this.properties);
222+
if (this.mappingResources != null) {
223+
entityManagerFactoryBean.setMappingResources(this.mappingResources);
224+
}
206225
URL rootLocation = EntityManagerFactoryBuilder.this.persistenceUnitRootLocation;
207226
if (rootLocation != null) {
208227
entityManagerFactoryBean

0 commit comments

Comments
 (0)