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


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

    发现存在一些问题:
    需要配置多个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>
  • 相关阅读:
    mysql 清空数据
    centos 7 安装搜狗输入法
    【分布式】分布式事务解决方案
    【Spring】事务的实现方式
    【Maven】 (请使用 -source 8 或更高版本以启用 lambda 表达式)
    【Redis】DENIED Redis is running in protected mode
    【Shiro】调用doGetAuthenticationInfo进行认证成功之后,isAuthenticated是false的问题。
    【线程池】ExecutorService与quartz搭配出现的问题
    【jenkins】jenkins执行nohup java报错
    【MySQL】mac环境下使用navicat premium连接mysql乱码问题
  • 原文地址:https://www.cnblogs.com/tangyanbo/p/4282195.html
Copyright © 2020-2023  润新知