Spring+Hibernate实现动态SessionFactory切换(改进版)

前面写了一篇关于动态切换Hibernate SessionFactory的文章,原文地址:http://tangyanbo.iteye.com/admin/blogs/1717402

发现存在一些问题:
需要配置多个HibernateTransactionManager和多个Spring 切面
这样带来两个问题
1. 程序效率降低,因为Spring进行多次Advice的拦截
2. 如果其中一个SessionFactory连接出现问题,会导致整个系统无法工作

今天研究出一种新的方法来解决此类问题
1. 数据源及Hibernate SessionFactory配置:

 

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
    <!-- FOR SqlServer-->  
    <bean id="SqlServer_DataSource"  
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
        <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />  
        <property name="url"  
            value="url" />  
        <property name="username" value="username" />  
        <property name="password" value="password" />  
    </bean>  
    <bean id="SqlServer_SessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"  
        p:mappingLocations="classpath:/com/entity/*.hbm.xml">  
        <property name="dataSource" ref="SqlServer_DataSource" />       
        <property name="hibernateProperties">  
            <props>                 
                <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>  
                <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>               
                <prop key="hibernate.show_sql">true</prop>  
                <prop key="hibernate.format_sql">true</prop>  
            </props>  
        </property>  
    </bean>  
   
      
    <!-- FOR Oracle -->  
    <bean id="Oracle _DataSource"  
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">       
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />  
        <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl" />  
        <property name="username" value="username" />  
        <property name="password" value="password" />  
    </bean>  
    <bean id="Oracle_SessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"   
        p:mappingLocations="classpath:/com/entity/*.hbm.xml">  
        <property name="dataSource" ref="Oracle_DataSource" />          
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>  
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>               
                <prop key="hibernate.show_sql">true</prop>  
                <prop key="hibernate.format_sql">true</prop>  
            </props>  
        </property>  
    </bean>  
  
      
      
</beans>  

 

2. 定义扩展接口DynamicSessionFactoryInf继承SessionFactory

 

 

import org.hibernate.SessionFactory;

public interface DynamicSessionFactoryInf extends SessionFactory {

	public SessionFactory getHibernateSessionFactory();
}

 

3. 定义DynamicSessionFactory实现DynamicSessionFactoryInf

 

public class DynamicSessionFactory implements DynamicSessionFactoryInf ,ApplicationContextAware{
	
	private static final long serialVersionUID = 1L;

	private ApplicationContext applicationContext;
	//动态调用SessionFactory
	private SessionFactory getHibernateSessionFactory(String name) {
		return (SessionFactory) applicationContext.getBean(name);
	}
        //实现DynamicSessionFactoryInf 接口的方法
	public SessionFactory getHibernateSessionFactory() {
		return getHibernateSessionFactory(ThreadLocalUtil.getCurrentITAsset()
				.getSessionFactoryName());
	}
	
       //以下是实现SessionFactory接口的方法,并对当前的SessionFactory实体进行代理
	public Reference getReference() throws NamingException {
		return getHibernateSessionFactory().getReference();
	}

	

	public Session openSession() throws HibernateException {
		return getHibernateSessionFactory().openSession();
	}

	public Session openSession(Interceptor interceptor)
			throws HibernateException {
		return getHibernateSessionFactory().openSession(interceptor);
	}

	public Session openSession(Connection connection) {
		return getHibernateSessionFactory().openSession(connection);
	}

	public Session openSession(Connection connection, Interceptor interceptor) {
		return getHibernateSessionFactory().openSession(connection,interceptor);
	}

	public Session getCurrentSession() throws HibernateException {
		return getHibernateSessionFactory().getCurrentSession();
	}

	public StatelessSession openStatelessSession() {
		return getHibernateSessionFactory().openStatelessSession();
	}

	public StatelessSession openStatelessSession(Connection connection) {
		return getHibernateSessionFactory().openStatelessSession(connection);
	}

	public ClassMetadata getClassMetadata(Class entityClass) {
		return getHibernateSessionFactory().getClassMetadata(entityClass);
	}

	public ClassMetadata getClassMetadata(String entityName) {
		return getHibernateSessionFactory().getClassMetadata(entityName);
	}

	public CollectionMetadata getCollectionMetadata(String roleName) {
		return getHibernateSessionFactory().getCollectionMetadata(roleName);
	}

	public Map getAllClassMetadata() {
		return getHibernateSessionFactory().getAllClassMetadata();
	}

	public Map getAllCollectionMetadata() {
		return getHibernateSessionFactory().getAllCollectionMetadata();
	}

	public Statistics getStatistics() {
		return getHibernateSessionFactory().getStatistics();
	}

	public void close() throws HibernateException {
		getHibernateSessionFactory().close();
	}

	public boolean isClosed() {
		return getHibernateSessionFactory().isClosed();
	}

	public Cache getCache() {
		return getHibernateSessionFactory().getCache();
	}

	public void evict(Class persistentClass) throws HibernateException {
		getHibernateSessionFactory().evict(persistentClass);
	}

	public void evict(Class persistentClass, Serializable id)
			throws HibernateException {
		getHibernateSessionFactory().evict(persistentClass, id);
	}

	public void evictEntity(String entityName) throws HibernateException {
		getHibernateSessionFactory().evictEntity(entityName);
	}

	public void evictEntity(String entityName, Serializable id)
			throws HibernateException {
		getHibernateSessionFactory().evictEntity(entityName, id);
	}

	public void evictCollection(String roleName) throws HibernateException {
		getHibernateSessionFactory().evictCollection(roleName);
	}

	public void evictCollection(String roleName, Serializable id)
			throws HibernateException {
		getHibernateSessionFactory().evictCollection(roleName, id);
	}

	public void evictQueries(String cacheRegion) throws HibernateException {
		getHibernateSessionFactory().evictQueries(cacheRegion);
	}

	public void evictQueries() throws HibernateException {
		getHibernateSessionFactory().evictQueries();
	}

	public Set getDefinedFilterNames() {
		return getHibernateSessionFactory().getDefinedFilterNames();
	}

	public FilterDefinition getFilterDefinition(String filterName)
			throws HibernateException {
		return getHibernateSessionFactory().getFilterDefinition(filterName);
	}

	public boolean containsFetchProfileDefinition(String name) {
		return getHibernateSessionFactory().containsFetchProfileDefinition(name);
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	

}

 

4. 配置动态SessionFactory

 

<bean id="sessionFactory" class="com.hp.it.qdpadmin.common.DynamicSessionFactory"/> 
 

 

5. 定义DynamicTransactionManager继承HibernateTransactionManager

 

public class DynamicTransactionManager extends HibernateTransactionManager {

	private static final long serialVersionUID = 1047039346475978451L;
	//重写getDataSource方法,实现动态获取
	public DataSource getDataSource() {
		DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory());
		return sfds;
	}
       //重写getSessionFactory方法,实现动态获取SessionFactory
	public SessionFactory getSessionFactory() {
		DynamicSessionFactoryInf dynamicSessionFactory = (DynamicSessionFactoryInf) super
				.getSessionFactory();
		SessionFactory hibernateSessionFactory = dynamicSessionFactory
				.getHibernateSessionFactory();
		return hibernateSessionFactory;
	}
	//重写afterPropertiesSet,跳过数据源的初始化等操作
	public void afterPropertiesSet() {
		return;
	}

}

 

6. 配置dynamicTransactionManager

 

<bean id="dynamicTransactionManager"
		class="com.hp.it.qdpadmin.common.DynamicTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
 

 

7. 为SessionFactory配置事务切面

 

<tx:advice id="dynamicTxAdvice" transaction-manager="dynamicTransactionManager">  
        <tx:attributes>  
            <tx:method name="get*" read-only="true" />  
            <tx:method name="find*" read-only="true" />  
            <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />  
        </tx:attributes>  
    </tx:advice>  
      
      
    <aop:config proxy-target-class="true">    
        <aop:pointcut id="txPointcut" expression="execution(* com.service.*.*(..))"/>          
        <aop:advisor advice-ref="dynamicTxAdvice" pointcut-ref="txPointcut" /> 
    </aop:config>  

你可能感兴趣的:(spring,Hibernate)