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>  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章