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.
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 *
8686public 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