Skip to content

Commit 4ae893e

Browse files
committed
DefaultPersistenceUnitManager detects META-INF/orm.xml for scanned default unit
Note: A default orm.xml file is only being used when not co-located with a persistence.xml file, since we assume it is intended for use with that persistence.xml file only then. Issue: SPR-11234 Issue: SPR-11260
1 parent 3370f8b commit 4ae893e

File tree

2 files changed

+85
-9
lines changed

2 files changed

+85
-9
lines changed

spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -134,6 +134,7 @@ public void setPersistenceXmlLocation(String persistenceXmlLocation) {
134134
* Uses the specified persistence unit name as the name of the default
135135
* persistence unit, if applicable.
136136
* <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
137+
* @see DefaultPersistenceUnitManager#setDefaultPersistenceUnitName
137138
*/
138139
@Override
139140
public void setPersistenceUnitName(String persistenceUnitName) {
@@ -149,10 +150,17 @@ public void setPersistenceUnitName(String persistenceUnitName) {
149150
* <p>Default is none. Specify packages to search for autodetection of your entity
150151
* classes in the classpath. This is analogous to Spring's component-scan feature
151152
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
153+
* <p>If no explicit {@link #setMappingResources mapping resources} have been
154+
* specified in addition to these packages, Spring's setup looks for a default
155+
* {@code META-INF/orm.xml} file in the classpath, registering it as a mapping
156+
* resource for the default unit if the mapping file is not co-located with a
157+
* {@code persistence.xml} file (in which case we assume it is only meant to be
158+
* used with the persistence units defined there, like in standard JPA).
152159
* <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
153160
* @param packagesToScan one or more base packages to search, analogous to
154161
* Spring's component-scan configuration for regular Spring components
155162
* @see #setPersistenceUnitManager
163+
* @see DefaultPersistenceUnitManager#setPackagesToScan
156164
*/
157165
public void setPackagesToScan(String... packagesToScan) {
158166
this.internalPersistenceUnitManager.setPackagesToScan(packagesToScan);
@@ -166,8 +174,19 @@ public void setPackagesToScan(String... packagesToScan) {
166174
* <p>Note that mapping resources must be relative to the classpath root,
167175
* e.g. "META-INF/mappings.xml" or "com/mycompany/repository/mappings.xml",
168176
* so that they can be loaded through {@code ClassLoader.getResource}.
177+
* <p>If no explicit mapping resources have been specified next to
178+
* {@link #setPackagesToScan packages to scan}, Spring's setup looks for a default
179+
* {@code META-INF/orm.xml} file in the classpath, registering it as a mapping
180+
* resource for the default unit if the mapping file is not co-located with a
181+
* {@code persistence.xml} file (in which case we assume it is only meant to be
182+
* used with the persistence units defined there, like in standard JPA).
183+
* <p>Note that specifying an empty array/list here suppresses the default
184+
* {@code META-INF/orm.xml} check. On the other hand, explicitly specifying
185+
* {@code META-INF/orm.xml} here will register that file even if it happens
186+
* to be co-located with a {@code persistence.xml} file.
169187
* <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
170188
* @see #setPersistenceUnitManager
189+
* @see DefaultPersistenceUnitManager#setMappingResources
171190
*/
172191
public void setMappingResources(String... mappingResources) {
173192
this.internalPersistenceUnitManager.setMappingResources(mappingResources);

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@
6969
* with configurable file locations, JDBC DataSource lookup and load-time weaving.
7070
*
7171
* <p>The default XML file location is {@code classpath*:META-INF/persistence.xml},
72-
* scanning for all matching files in the class path (as defined in the JPA specification).
72+
* scanning for all matching files in the classpath (as defined in the JPA specification).
7373
* DataSource names are by default interpreted as JNDI names, and no load time weaving
7474
* is available (which requires weaving to be turned off in the persistence provider).
7575
*
@@ -86,22 +86,26 @@
8686
public class DefaultPersistenceUnitManager
8787
implements PersistenceUnitManager, ResourceLoaderAware, LoadTimeWeaverAware, InitializingBean {
8888

89+
private static final String ENTITY_CLASS_RESOURCE_PATTERN = "/**/*.class";
90+
91+
private static final String DEFAULT_ORM_XML_RESOURCE = "META-INF/orm.xml";
92+
93+
private static final String PERSISTENCE_XML_FILENAME = "persistence.xml";
94+
8995
/**
9096
* Default location of the {@code persistence.xml} file:
9197
* "classpath*:META-INF/persistence.xml".
9298
*/
93-
public final static String DEFAULT_PERSISTENCE_XML_LOCATION = "classpath*:META-INF/persistence.xml";
99+
public final static String DEFAULT_PERSISTENCE_XML_LOCATION = "classpath*:META-INF/" + PERSISTENCE_XML_FILENAME;
94100

95101
/**
96102
* Default location for the persistence unit root URL:
97-
* "classpath:", indicating the root of the class path.
103+
* "classpath:", indicating the root of the classpath.
98104
*/
99105
public final static String ORIGINAL_DEFAULT_PERSISTENCE_UNIT_ROOT_LOCATION = "classpath:";
100106

101107
public final static String ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME = "default";
102108

103-
private static final String ENTITY_CLASS_RESOURCE_PATTERN = "/**/*.class";
104-
105109

106110
private static final Set<TypeFilter> entityTypeFilters;
107111

@@ -178,9 +182,9 @@ public void setPersistenceXmlLocations(String... persistenceXmlLocations) {
178182
/**
179183
* Set the default persistence unit root location, to be applied
180184
* if no unit-specific persistence unit root could be determined.
181-
* <p>Default is "classpath:", that is, the root of the current class path
185+
* <p>Default is "classpath:", that is, the root of the current classpath
182186
* (nearest root directory). To be overridden if unit-specific resolution
183-
* does not work and the class path root is not appropriate either.
187+
* does not work and the classpath root is not appropriate either.
184188
*/
185189
public void setDefaultPersistenceUnitRootLocation(String defaultPersistenceUnitRootLocation) {
186190
this.defaultPersistenceUnitRootLocation = defaultPersistenceUnitRootLocation;
@@ -205,6 +209,18 @@ public void setDefaultPersistenceUnitName(String defaultPersistenceUnitName) {
205209
* <p>Default is none. Specify packages to search for autodetection of your entity
206210
* classes in the classpath. This is analogous to Spring's component-scan feature
207211
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
212+
* <p>Such package scanning defines a "default persistence unit" in Spring, which
213+
* may live next to regularly defined units originating from {@code persistence.xml}.
214+
* Its name is determined by {@link #setDefaultPersistenceUnitName}: by default,
215+
* it's simply "default".
216+
* <p>If no explicit {@link #setMappingResources mapping resources} have been
217+
* specified in addition to these packages, this manager looks for a default
218+
* {@code META-INF/orm.xml} file in the classpath, registering it as a mapping
219+
* resource for the default unit if the mapping file is not co-located with a
220+
* {@code persistence.xml} file (in which case we assume it is only meant to be
221+
* used with the persistence units defined there, like in standard JPA).
222+
* @see #setDefaultPersistenceUnitName
223+
* @see #setMappingResources
208224
*/
209225
public void setPackagesToScan(String... packagesToScan) {
210226
this.packagesToScan = packagesToScan;
@@ -218,6 +234,17 @@ public void setPackagesToScan(String... packagesToScan) {
218234
* <p>Note that mapping resources must be relative to the classpath root,
219235
* e.g. "META-INF/mappings.xml" or "com/mycompany/repository/mappings.xml",
220236
* so that they can be loaded through {@code ClassLoader.getResource}.
237+
* <p>If no explicit mapping resources have been specified next to
238+
* {@link #setPackagesToScan packages to scan}, this manager looks for a default
239+
* {@code META-INF/orm.xml} file in the classpath, registering it as a mapping
240+
* resource for the default unit if the mapping file is not co-located with a
241+
* {@code persistence.xml} file (in which case we assume it is only meant to be
242+
* used with the persistence units defined there, like in standard JPA).
243+
* <p>Note that specifying an empty array/list here suppresses the default
244+
* {@code META-INF/orm.xml} check. On the other hand, explicitly specifying
245+
* {@code META-INF/orm.xml} here will register that file even if it happens
246+
* to be co-located with a {@code persistence.xml} file.
247+
* @see #setDefaultPersistenceUnitName
221248
* @see #setPackagesToScan
222249
*/
223250
public void setMappingResources(String... mappingResources) {
@@ -480,6 +507,7 @@ private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {
480507
SpringPersistenceUnitInfo scannedUnit = new SpringPersistenceUnitInfo();
481508
scannedUnit.setPersistenceUnitName(this.defaultPersistenceUnitName);
482509
scannedUnit.setExcludeUnlistedClasses(true);
510+
483511
if (this.packagesToScan != null) {
484512
for (String pkg : this.packagesToScan) {
485513
try {
@@ -508,11 +536,16 @@ private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {
508536
}
509537
}
510538
}
539+
511540
if (this.mappingResources != null) {
512541
for (String mappingFileName : this.mappingResources) {
513542
scannedUnit.addMappingFileName(mappingFileName);
514543
}
515544
}
545+
else if (useOrmXmlForDefaultPersistenceUnit()) {
546+
scannedUnit.addMappingFileName(DEFAULT_ORM_XML_RESOURCE);
547+
}
548+
516549
return scannedUnit;
517550
}
518551

@@ -548,6 +581,30 @@ private URL determineDefaultPersistenceUnitRootUrl() {
548581
}
549582
}
550583

584+
/**
585+
* Determine whether to register JPA's default "META-INF/orm.xml" with
586+
* Spring's default persistence unit, if any.
587+
* <p>Checks whether a "META-INF/orm.xml" file exists in the classpath and
588+
* uses it if it is not co-located with a "META-INF/persistence.xml" file.
589+
*/
590+
private boolean useOrmXmlForDefaultPersistenceUnit() {
591+
Resource ormXml = this.resourcePatternResolver.getResource(
592+
this.defaultPersistenceUnitRootLocation + DEFAULT_ORM_XML_RESOURCE);
593+
if (ormXml.exists()) {
594+
try {
595+
Resource persistenceXml = ormXml.createRelative(PERSISTENCE_XML_FILENAME);
596+
if (!persistenceXml.exists()) {
597+
return true;
598+
}
599+
}
600+
catch (IOException ex) {
601+
// Cannot resolve relative persistence.xml file - let's assume it's not there.
602+
return true;
603+
}
604+
}
605+
return false;
606+
}
607+
551608

552609
/**
553610
* Return the specified PersistenceUnitInfo from this manager's cache

0 commit comments

Comments
 (0)