From 92816492edd50b9791cbbc4129fc79eaf71fac98 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 10 Dec 2013 16:47:17 +0100 Subject: [PATCH] Established well-defined registration order for Hibernate package scanning Issue: SPR-7742 --- .../LocalSessionFactoryBuilder.java | 17 +++++++++++++--- .../AnnotationSessionFactoryBean.java | 20 ++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java b/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java index 36bfcd76d3f..7182c957a8c 100644 --- a/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java +++ b/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java @@ -22,6 +22,7 @@ import java.lang.reflect.Method; import java.util.LinkedHashSet; import java.util.Properties; import java.util.Set; +import java.util.TreeSet; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.MappedSuperclass; @@ -249,6 +250,8 @@ public class LocalSessionFactoryBuilder extends Configuration { * @throws HibernateException if scanning fails for any reason */ public LocalSessionFactoryBuilder scanPackages(String... packagesToScan) throws HibernateException { + Set classNames = new TreeSet(); + Set packageNames = new TreeSet(); try { for (String pkg : packagesToScan) { String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + @@ -260,22 +263,30 @@ public class LocalSessionFactoryBuilder extends Configuration { MetadataReader reader = readerFactory.getMetadataReader(resource); String className = reader.getClassMetadata().getClassName(); if (matchesEntityTypeFilter(reader, readerFactory)) { - addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className)); + classNames.add(className); } else if (className.endsWith(PACKAGE_INFO_SUFFIX)) { - addPackage(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); + packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); } } } } - return this; } catch (IOException ex) { throw new MappingException("Failed to scan classpath for unlisted classes", ex); } + try { + for (String className : classNames) { + addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className)); + } + for (String packageName : packageNames) { + addPackage(packageName); + } + } catch (ClassNotFoundException ex) { throw new MappingException("Failed to load annotated classes from classpath", ex); } + return this; } /** diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java index b6267ad4759..cf2d60e0df1 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java @@ -17,7 +17,8 @@ package org.springframework.orm.hibernate3.annotation; import java.io.IOException; - +import java.util.Set; +import java.util.TreeSet; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.MappedSuperclass; @@ -25,6 +26,7 @@ import javax.persistence.MappedSuperclass; import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.cfg.Configuration; + import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; @@ -67,6 +69,8 @@ import org.springframework.util.ClassUtils; * <property name="packagesToScan" value="test.package"/> * </bean> * + *

Requires Hibernate 3.6 or later, as of Spring 4.0. + * * @author Juergen Hoeller * @since 1.2.2 * @see #setDataSource @@ -168,6 +172,8 @@ public class AnnotationSessionFactoryBean extends LocalSessionFactoryBean implem */ protected void scanPackages(Configuration config) { if (this.packagesToScan != null) { + Set classNames = new TreeSet(); + Set packageNames = new TreeSet(); try { for (String pkg : this.packagesToScan) { String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + @@ -179,10 +185,10 @@ public class AnnotationSessionFactoryBean extends LocalSessionFactoryBean implem MetadataReader reader = readerFactory.getMetadataReader(resource); String className = reader.getClassMetadata().getClassName(); if (matchesEntityTypeFilter(reader, readerFactory)) { - config.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className)); + classNames.add(className); } else if (className.endsWith(PACKAGE_INFO_SUFFIX)) { - config.addPackage(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); + packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); } } } @@ -191,6 +197,14 @@ public class AnnotationSessionFactoryBean extends LocalSessionFactoryBean implem catch (IOException ex) { throw new MappingException("Failed to scan classpath for unlisted classes", ex); } + try { + for (String className : classNames) { + config.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className)); + } + for (String packageName : packageNames) { + config.addPackage(packageName); + } + } catch (ClassNotFoundException ex) { throw new MappingException("Failed to load annotated classes from classpath", ex); }