diff --git a/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java b/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java new file mode 100644 index 0000000000..6f2dd82036 --- /dev/null +++ b/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.orm.jpa.vendor; + +import java.util.Map; +import javax.persistence.EntityManagerFactory; +import javax.persistence.spi.PersistenceUnitInfo; + +import org.hibernate.cfg.Configuration; +import org.hibernate.jpa.HibernatePersistenceProvider; +import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl; +import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; +import org.hibernate.service.ServiceRegistry; + +import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo; + +/** + * Spring-specific subclass of the standard {@link HibernatePersistenceProvider} + * from the {@code org.hibernate.jpa} package, adding support for + * {@link SmartPersistenceUnitInfo#getManagedPackages()}. + * + *

Compatible with Hibernate 4.3. {@link SpringHibernateEjbPersistenceProvider} + * is an alternative for compatibility with earlier Hibernate versions (3.6-4.2). + * + * @author Juergen Hoeller + * @since 4.1 + */ +class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider { + + @Override + @SuppressWarnings("rawtypes") + public EntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo info, Map properties) { + return new EntityManagerFactoryBuilderImpl(new PersistenceUnitInfoDescriptor(info), properties) { + @Override + public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry) { + Configuration configuration = super.buildHibernateConfiguration(serviceRegistry); + if (info instanceof SmartPersistenceUnitInfo) { + for (String managedPackage : ((SmartPersistenceUnitInfo) info).getManagedPackages()) { + configuration.addPackage(managedPackage); + } + } + return configuration; + } + }.build(); + } + +} diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java index fa8a7a13a4..a9dfd32b9b 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java @@ -86,7 +86,9 @@ import org.springframework.util.ResourceUtils; public class DefaultPersistenceUnitManager implements PersistenceUnitManager, ResourceLoaderAware, LoadTimeWeaverAware, InitializingBean { - private static final String ENTITY_CLASS_RESOURCE_PATTERN = "/**/*.class"; + private static final String CLASS_RESOURCE_PATTERN = "/**/*.class"; + + private static final String PACKAGE_INFO_SUFFIX = ".package-info"; private static final String DEFAULT_ORM_XML_RESOURCE = "META-INF/orm.xml"; @@ -512,7 +514,7 @@ public class DefaultPersistenceUnitManager for (String pkg : this.packagesToScan) { try { String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + - ClassUtils.convertClassNameToResourcePath(pkg) + ENTITY_CLASS_RESOURCE_PATTERN; + ClassUtils.convertClassNameToResourcePath(pkg) + CLASS_RESOURCE_PATTERN; Resource[] resources = this.resourcePatternResolver.getResources(pattern); MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); for (Resource resource : resources) { @@ -528,6 +530,10 @@ public class DefaultPersistenceUnitManager } } } + else if (className.endsWith(PACKAGE_INFO_SUFFIX)) { + scannedUnit.addManagedPackage( + className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); + } } } } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java index 96dff70d3e..5da76248b6 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,13 +53,15 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo { private DataSource jtaDataSource; - private List mappingFileNames = new LinkedList(); + private final List mappingFileNames = new LinkedList(); private List jarFileUrls = new LinkedList(); private URL persistenceUnitRootUrl; - private List managedClassNames = new LinkedList(); + private final List managedClassNames = new LinkedList(); + + private final List managedPackages = new LinkedList(); private boolean excludeUnlistedClasses = false; @@ -161,6 +163,15 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo { return this.managedClassNames; } + public void addManagedPackage(String packageName) { + this.managedPackages.add(packageName); + } + + @Override + public List getManagedPackages() { + return this.managedPackages; + } + public void setExcludeUnlistedClasses(boolean excludeUnlistedClasses) { this.excludeUnlistedClasses = excludeUnlistedClasses; } @@ -251,13 +262,7 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("PersistenceUnitInfo: name '"); - builder.append(this.persistenceUnitName); - builder.append("', root URL ["); - builder.append(this.persistenceUnitRootUrl); - builder.append("]"); - return builder.toString(); + return "PersistenceUnitInfo: name '" + this.persistenceUnitName + "', root URL [" + this.persistenceUnitRootUrl + "]"; } } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SmartPersistenceUnitInfo.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SmartPersistenceUnitInfo.java index a5dd4affad..4ed2777520 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SmartPersistenceUnitInfo.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/SmartPersistenceUnitInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.orm.jpa.persistenceunit; +import java.util.List; import javax.persistence.spi.PersistenceUnitInfo; /** @@ -30,6 +31,14 @@ import javax.persistence.spi.PersistenceUnitInfo; */ public interface SmartPersistenceUnitInfo extends PersistenceUnitInfo { + /** + * Return a list of managed Java packages, to be introspected by the persistence provider. + * Typically found through scanning but not exposable through {@link #getManagedClassNames()}. + * @return a list of names of managed Java packages (potentially empty) + * @since 4.1 + */ + List getManagedPackages(); + /** * Set the persistence provider's own package name, for exclusion from class transformation. * @see #addTransformer(javax.persistence.spi.ClassTransformer) diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java index f26e54569b..eceada62e0 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,9 +32,6 @@ import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle9iDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SQLServerDialect; -import org.hibernate.ejb.HibernateEntityManager; -import org.hibernate.ejb.HibernateEntityManagerFactory; -import org.hibernate.ejb.HibernatePersistence; import org.springframework.orm.jpa.JpaDialect; @@ -68,25 +65,28 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { @SuppressWarnings({"deprecation", "unchecked"}) public HibernateJpaVendorAdapter() { - PersistenceProvider providerToUse; + ClassLoader cl = HibernateJpaVendorAdapter.class.getClassLoader(); Class emfIfcToUse; Class emIfcToUse; + Class providerClass; + PersistenceProvider providerToUse; try { - // Try Hibernate 4.3's org.hibernate.jpa package in order to avoid deprecation warnings - ClassLoader cl = HibernateJpaVendorAdapter.class.getClassLoader(); - Class hibernatePersistenceProviderClass = cl.loadClass("org.hibernate.jpa.HibernatePersistenceProvider"); - providerToUse = (PersistenceProvider) hibernatePersistenceProviderClass.newInstance(); - emfIfcToUse = (Class) cl.loadClass("org.hibernate.jpa.HibernateEntityManagerFactory"); - emIfcToUse = (Class) cl.loadClass("org.hibernate.jpa.HibernateEntityManager"); - } - catch (ClassNotFoundException ex) { - // Fall back to Hibernate 3.6-4.2 org.hibernate.ejb package - providerToUse = new HibernatePersistence(); - emfIfcToUse = HibernateEntityManagerFactory.class; - emIfcToUse = HibernateEntityManager.class; + try { + // Try Hibernate 4.3's org.hibernate.jpa package in order to avoid deprecation warnings + emfIfcToUse = (Class) cl.loadClass("org.hibernate.jpa.HibernateEntityManagerFactory"); + emIfcToUse = (Class) cl.loadClass("org.hibernate.jpa.HibernateEntityManager"); + providerClass = cl.loadClass("org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider"); + } + catch (ClassNotFoundException ex) { + // Fall back to Hibernate 3.6-4.2 org.hibernate.ejb package + emfIfcToUse = (Class) cl.loadClass("org.hibernate.ejb.HibernateEntityManagerFactory"); + emIfcToUse = (Class) cl.loadClass("org.hibernate.ejb.HibernateEntityManager"); + providerClass = cl.loadClass("org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider"); + } + providerToUse = (PersistenceProvider) providerClass.newInstance(); } catch (Exception ex) { - throw new IllegalStateException("Found HibernatePersistenceProvider but could not instantiate it", ex); + throw new IllegalStateException("Failed to determine Hibernate PersistenceProvider", ex); } this.persistenceProvider = providerToUse; this.entityManagerFactoryInterface = emfIfcToUse; diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateEjbPersistenceProvider.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateEjbPersistenceProvider.java new file mode 100644 index 0000000000..11a6e4f6a6 --- /dev/null +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateEjbPersistenceProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.orm.jpa.vendor; + +import java.util.Map; +import javax.persistence.EntityManagerFactory; +import javax.persistence.spi.PersistenceUnitInfo; + +import org.hibernate.ejb.Ejb3Configuration; +import org.hibernate.ejb.HibernatePersistence; + +import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo; + +/** + * Spring-specific subclass of the standard {@link HibernatePersistence} + * provider from the {@code org.hibernate.ejb} package, adding support for + * {@link SmartPersistenceUnitInfo#getManagedPackages()}. + * + *

Compatible with Hibernate 3.6 as well as 4.0-4.2. + * + * @author Juergen Hoeller + * @since 4.1 + */ +class SpringHibernateEjbPersistenceProvider extends HibernatePersistence { + + @SuppressWarnings("rawtypes") + public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) { + Ejb3Configuration cfg = new Ejb3Configuration(); + if (info instanceof SmartPersistenceUnitInfo) { + for (String managedPackage : ((SmartPersistenceUnitInfo) info).getManagedPackages()) { + cfg.addPackage(managedPackage); + } + } + Ejb3Configuration configured = cfg.configure(info, properties); + return (configured != null ? configured.buildEntityManagerFactory() : null); + } + +}