package com.sly.core.hibernate.support;import java.io.IOException;import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.util.ClassUtils;/**
 * 借助spring扫描来
 * 实现hibernate的zero configuration
 * 无需hibernate.cfg.xml文件
 * @author shenly
 *<bean id="sessionFactory" class="com.sly.core.hibernate.support.AutoScanAnnotationSessionFactory">
        <property name="dataSource" ref="dataSource"/>
                                               
        <property name="scanPackage" value="com.sly"></property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${test.hibernate.dialect}
                hibernate.query.substitutions=true 'Y', false 'N'
                hibernate.cache.use_second_level_cache=true
                hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
                hibernate.hbm2ddl.auto=update
            </value>
            <!-- Turn batching off for better error messages under PostgreSQL -->
            <!-- hibernate.jdbc.batch_size=0 -->
        </property>
    </bean>
 */
public class AutoScanAnnotationSessionFactory extends AnnotationSessionFactoryBean {
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private TypeFilter[] entityTypeFilters = new TypeFilter[] { new AnnotationTypeFilter(Entity.class, false),
new AnnotationTypeFilter(Embeddable.class, false), new AnnotationTypeFilter(MappedSuperclass.class, false),
new AnnotationTypeFilter(org.hibernate.annotations.Entity.class, false) };
private String pkg; /**
 * 装配bean时需要指定扫描路径
 * @param path
 */
public void setScanPackage(String path) {
pkg = path;
} @Override
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
super.postProcessAnnotationConfiguration(config);
if (StringUtils.isNotBlank(pkg)) {
autoScan(config);
}
} private void autoScan(AnnotationConfiguration cfg) {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(pkg) + "/**/*.class";
try {
Resource[] resources = this.resourcePatternResolver.getResources(pattern);
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
if (matchesFilter(reader, readerFactory)) {
cfg.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));
}
}
}
} catch (IOException ioEx) { } catch (ClassNotFoundException notFoundEx) { } } private boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {
if (this.entityTypeFilters != null) {
for (TypeFilter filter : this.entityTypeFilters) {
if (filter.match(reader, readerFactory)) {
return true;
}
}
}
return false;
}
}