Skip to content

Commit f9452ae

Browse files
committed
LocalSessionFactoryBean supports JPA 2.1 auto-apply @converter on Hibernate 4.3
Issue: SPR-12234
1 parent 9c8f7d9 commit f9452ae

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import java.io.IOException;
2020
import java.lang.annotation.Annotation;
2121
import java.lang.reflect.Method;
22-
import java.util.LinkedHashSet;
2322
import java.util.Properties;
2423
import java.util.Set;
2524
import java.util.TreeSet;
25+
import javax.persistence.AttributeConverter;
2626
import javax.persistence.Embeddable;
2727
import javax.persistence.Entity;
2828
import javax.persistence.MappedSuperclass;
@@ -83,32 +83,33 @@ public class LocalSessionFactoryBuilder extends Configuration {
8383

8484
private static final String PACKAGE_INFO_SUFFIX = ".package-info";
8585

86+
private static final TypeFilter[] DEFAULT_ENTITY_TYPE_FILTERS = new TypeFilter[] {
87+
new AnnotationTypeFilter(Entity.class, false),
88+
new AnnotationTypeFilter(Embeddable.class, false),
89+
new AnnotationTypeFilter(MappedSuperclass.class, false)};
8690

87-
private static final Set<TypeFilter> defaultTypeFilters;
91+
92+
private static TypeFilter converterTypeFilter;
8893

8994
static {
90-
defaultTypeFilters = new LinkedHashSet<TypeFilter>(4);
91-
defaultTypeFilters.add(new AnnotationTypeFilter(Entity.class, false));
92-
defaultTypeFilters.add(new AnnotationTypeFilter(Embeddable.class, false));
93-
defaultTypeFilters.add(new AnnotationTypeFilter(MappedSuperclass.class, false));
9495
try {
9596
@SuppressWarnings("unchecked")
9697
Class<? extends Annotation> converterAnnotation = (Class<? extends Annotation>)
9798
ClassUtils.forName("javax.persistence.Converter", LocalSessionFactoryBuilder.class.getClassLoader());
98-
defaultTypeFilters.add(new AnnotationTypeFilter(converterAnnotation, false));
99+
converterTypeFilter = new AnnotationTypeFilter(converterAnnotation, false);
99100
}
100101
catch (ClassNotFoundException ex) {
101102
// JPA 2.1 API not available - Hibernate <4.3
102103
}
103104
}
104105

105106

106-
private TypeFilter[] entityTypeFilters = defaultTypeFilters.toArray(new TypeFilter[defaultTypeFilters.size()]);
107-
108107
private final ResourcePatternResolver resourcePatternResolver;
109108

110109
private RegionFactory cacheRegionFactory;
111110

111+
private TypeFilter[] entityTypeFilters = DEFAULT_ENTITY_TYPE_FILTERS;
112+
112113

113114
/**
114115
* Create a new LocalSessionFactoryBuilder for the given DataSource.
@@ -272,7 +273,8 @@ public LocalSessionFactoryBuilder addPackages(String... annotatedPackages) {
272273
* @throws HibernateException if scanning fails for any reason
273274
*/
274275
public LocalSessionFactoryBuilder scanPackages(String... packagesToScan) throws HibernateException {
275-
Set<String> classNames = new TreeSet<String>();
276+
Set<String> entityClassNames = new TreeSet<String>();
277+
Set<String> converterClassNames = new TreeSet<String>();
276278
Set<String> packageNames = new TreeSet<String>();
277279
try {
278280
for (String pkg : packagesToScan) {
@@ -285,7 +287,10 @@ public LocalSessionFactoryBuilder scanPackages(String... packagesToScan) throws
285287
MetadataReader reader = readerFactory.getMetadataReader(resource);
286288
String className = reader.getClassMetadata().getClassName();
287289
if (matchesEntityTypeFilter(reader, readerFactory)) {
288-
classNames.add(className);
290+
entityClassNames.add(className);
291+
}
292+
else if (converterTypeFilter != null && converterTypeFilter.match(reader, readerFactory)) {
293+
converterClassNames.add(className);
289294
}
290295
else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {
291296
packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length()));
@@ -298,8 +303,12 @@ else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {
298303
throw new MappingException("Failed to scan classpath for unlisted classes", ex);
299304
}
300305
try {
301-
for (String className : classNames) {
302-
addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));
306+
ClassLoader cl = this.resourcePatternResolver.getClassLoader();
307+
for (String className : entityClassNames) {
308+
addAnnotatedClass(cl.loadClass(className));
309+
}
310+
for (String className : converterClassNames) {
311+
ConverterRegistrationDelegate.registerConverter(this, cl.loadClass(className));
303312
}
304313
for (String packageName : packageNames) {
305314
addPackage(packageName);
@@ -369,4 +378,16 @@ public SessionFactory buildSessionFactory() throws HibernateException {
369378
}
370379
}
371380

381+
382+
/**
383+
* Inner class to avoid hard dependency on JPA 2.1 / Hibernate 4.3.
384+
*/
385+
private static class ConverterRegistrationDelegate {
386+
387+
@SuppressWarnings("unchecked")
388+
public static void registerConverter(Configuration config, Class<?> converterClass) {
389+
config.addAttributeConverter((Class<? extends AttributeConverter<?, ?>>) converterClass);
390+
}
391+
}
392+
372393
}

0 commit comments

Comments
 (0)