LocalSessionFactoryBean supports JPA 2.1 auto-apply @Converter on Hibernate 4.3

Issue: SPR-12234
This commit is contained in:
Juergen Hoeller 2014-09-19 00:11:44 +02:00
parent 9c8f7d9246
commit f9452ae9e9
1 changed files with 34 additions and 13 deletions

View File

@ -19,10 +19,10 @@ package org.springframework.orm.hibernate4;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import javax.persistence.AttributeConverter;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
@ -83,19 +83,20 @@ public class LocalSessionFactoryBuilder extends Configuration {
private static final String PACKAGE_INFO_SUFFIX = ".package-info";
private static final TypeFilter[] DEFAULT_ENTITY_TYPE_FILTERS = new TypeFilter[] {
new AnnotationTypeFilter(Entity.class, false),
new AnnotationTypeFilter(Embeddable.class, false),
new AnnotationTypeFilter(MappedSuperclass.class, false)};
private static final Set<TypeFilter> defaultTypeFilters;
private static TypeFilter converterTypeFilter;
static {
defaultTypeFilters = new LinkedHashSet<TypeFilter>(4);
defaultTypeFilters.add(new AnnotationTypeFilter(Entity.class, false));
defaultTypeFilters.add(new AnnotationTypeFilter(Embeddable.class, false));
defaultTypeFilters.add(new AnnotationTypeFilter(MappedSuperclass.class, false));
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> converterAnnotation = (Class<? extends Annotation>)
ClassUtils.forName("javax.persistence.Converter", LocalSessionFactoryBuilder.class.getClassLoader());
defaultTypeFilters.add(new AnnotationTypeFilter(converterAnnotation, false));
converterTypeFilter = new AnnotationTypeFilter(converterAnnotation, false);
}
catch (ClassNotFoundException ex) {
// JPA 2.1 API not available - Hibernate <4.3
@ -103,12 +104,12 @@ public class LocalSessionFactoryBuilder extends Configuration {
}
private TypeFilter[] entityTypeFilters = defaultTypeFilters.toArray(new TypeFilter[defaultTypeFilters.size()]);
private final ResourcePatternResolver resourcePatternResolver;
private RegionFactory cacheRegionFactory;
private TypeFilter[] entityTypeFilters = DEFAULT_ENTITY_TYPE_FILTERS;
/**
* Create a new LocalSessionFactoryBuilder for the given DataSource.
@ -272,7 +273,8 @@ public class LocalSessionFactoryBuilder extends Configuration {
* @throws HibernateException if scanning fails for any reason
*/
public LocalSessionFactoryBuilder scanPackages(String... packagesToScan) throws HibernateException {
Set<String> classNames = new TreeSet<String>();
Set<String> entityClassNames = new TreeSet<String>();
Set<String> converterClassNames = new TreeSet<String>();
Set<String> packageNames = new TreeSet<String>();
try {
for (String pkg : packagesToScan) {
@ -285,7 +287,10 @@ public class LocalSessionFactoryBuilder extends Configuration {
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
if (matchesEntityTypeFilter(reader, readerFactory)) {
classNames.add(className);
entityClassNames.add(className);
}
else if (converterTypeFilter != null && converterTypeFilter.match(reader, readerFactory)) {
converterClassNames.add(className);
}
else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {
packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length()));
@ -298,8 +303,12 @@ public class LocalSessionFactoryBuilder extends Configuration {
throw new MappingException("Failed to scan classpath for unlisted classes", ex);
}
try {
for (String className : classNames) {
addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));
ClassLoader cl = this.resourcePatternResolver.getClassLoader();
for (String className : entityClassNames) {
addAnnotatedClass(cl.loadClass(className));
}
for (String className : converterClassNames) {
ConverterRegistrationDelegate.registerConverter(this, cl.loadClass(className));
}
for (String packageName : packageNames) {
addPackage(packageName);
@ -369,4 +378,16 @@ public class LocalSessionFactoryBuilder extends Configuration {
}
}
/**
* Inner class to avoid hard dependency on JPA 2.1 / Hibernate 4.3.
*/
private static class ConverterRegistrationDelegate {
@SuppressWarnings("unchecked")
public static void registerConverter(Configuration config, Class<?> converterClass) {
config.addAttributeConverter((Class<? extends AttributeConverter<?, ?>>) converterClass);
}
}
}