码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-02-10 13:03:31      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

场景:

1)系统有多个数据库

2)且数据库类型也不尽相同

3)现在应用根据某些条件路由到具体的数据库

4)且在spring+hibernate框架下,支持依赖注入

已有实现,spring动态数据源,但无法实现动态SessionFactory,即不通数据库的方言不一样

目标:

在spring动态数据源的基础上,实现动态SessionFactory

前面写了一篇关于动态切换Hibernate SessionFactory的文章,

原文地址:http://www.cnblogs.com/tangyanbo/p/4283482.html

发现存在一些问题:
需要配置多个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实现动态SessionFactory切换(改进版)

标签:

原文地址:http://www.cnblogs.com/tangyanbo/p/4283495.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!