首页 > hibernate spring 加载多个TransactionManager

hibernate spring 加载多个TransactionManager

我在用多个TransactionManager尝试不同数据库之间的切换,但是总是默认的第一个。
以下是我的XML配置

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <bean id="transactionManagerSS" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactorySS" />
    </bean>

    <bean id="routingTransactionManager" class="com.ivo.util.RoutingTransactionManager">
        <property name="targetTransactionManagers">
          <map value-type="org.springframework.transaction.PlatformTransactionManager">
            <entry key="transactionManager" value-ref="transactionManager" />
            <entry key="transactionManagerSS" value-ref="transactionManagerSS" />
          </map>
        </property>
      </bean>

这是我指定TransactionManager的类

import org.apache.commons.lang.Validate;
@SuppressWarnings("unchecked")
public class RoutingContextHolder<T> {
     
    @SuppressWarnings("rawtypes")
    private static final ThreadLocal contextHolder = new ThreadLocal();

      public static <T> void setContext(T context) {
        Validate.notNull(context, "必须指定路由的context");
        contextHolder.set(context);
      }

      public static <T> T getContext() {
        return (T) contextHolder.get();
      }
    }

这个类实现了PlatformTransactionManager


import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.Validate;
import org.hibernate.TransactionException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

public class RoutingTransactionManager implements PlatformTransactionManager{

    private Map<Object, PlatformTransactionManager> targetTransactionManagers = new HashMap<Object, PlatformTransactionManager>();

          /**
           * 根据给定的规则获取指定的tx
           * 
           * @return
           */
          protected PlatformTransactionManager getTargetTransactionManager() {
            Object context = RoutingContextHolder.getContext();
            Validate.notNull(context, "必须指定路由的context");
            return targetTransactionManagers.get(context);
          }

          public void setTargetTransactionManagers(Map<Object, PlatformTransactionManager> targetTransactionManagers) {
            this.targetTransactionManagers = targetTransactionManagers;
          }

          public void commit(TransactionStatus status) throws TransactionException {
            getTargetTransactionManager().commit(status);
          }

          public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
            return getTargetTransactionManager().getTransaction(definition);
          }

          public void rollback(TransactionStatus status) throws TransactionException {
            getTargetTransactionManager().rollback(status);
          }
}

我的调用是这样的:

RoutingContextHolder.setContext("transactionManagerSS");

报错是这样的

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'eimdb.rma_o_customer' doesn't exist
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)

搞了很久没看懂 希望大家能帮帮我~ Thanks in advance!
(这只是部分代码,如果需要详细的,请@我)

以下是两个Sessionfactory的配置

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSourceMS" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQLDialect
                </prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.cache.region.factory_class">
                    org.hibernate.cache.ehcache.EhCacheRegionFactory
                </prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.use_sql_comments">false</prop>
                <prop key="hibernate.jdbc.fetch_size">80</prop>
                <prop key="hibernate.jdbc.batch_size">80</prop>
                <prop key="hibernate.jdbc.use_streams_for_binary">
                    true
                </prop>
                <prop key="hibernate.current_session_context_class">
                    org.springframework.orm.hibernate4.SpringSessionContext
                </prop>
                <prop key="hibernate.cache.use_second_level_cache">
                    true
                </prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
            </props>
        </property>
        <property name="packagesToScan" value="com.ivo.*" />
    </bean>

    <bean id="sessionFactorySS" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSourceSS" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.SQLServerDialect
                </prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.cache.region.factory_class">
                    org.hibernate.cache.ehcache.EhCacheRegionFactory
                </prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.use_sql_comments">false</prop>
                <prop key="hibernate.jdbc.fetch_size">80</prop>
                <prop key="hibernate.jdbc.batch_size">80</prop>
                <prop key="hibernate.jdbc.use_streams_for_binary">
                    true
                </prop>
                <prop key="hibernate.current_session_context_class">
                    org.springframework.orm.hibernate4.SpringSessionContext
                </prop>
                <prop key="hibernate.cache.use_second_level_cache">
                    true
                </prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
            </props>
        </property>
        <property name="packagesToScan" value="com.ivo.*" />
    </bean>

这是datasource

    <bean id="dataSourceMS" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="**" />
        <property name="username" value="root"/>
        <property name="password" value="root"/>
         
        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="1" />
        <property name="minIdle" value="1"/>
        <property name="maxActive" value="8" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="3000"/>
        <!-- 配置间隔多久才进行一次检测(启动destroy线程),检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒;即最多允许一个连接空闲多长时间,超出此时间的连接,会被destroy线程关闭 -->
        <property name="minEvictableIdleTimeMillis" value="300000" />
        <!-- 对空闲接连再被使用时,如果空闲时间超过timeBetweenEvictionRunsMillis,会发出验证sql进行有效检测 -->
        <property name="validationQuery" value="SELECT 'x'" />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <!-- 移除执行超时的sql,单位是毫秒 -->
        <property name="removeAbandoned" value="true"/>
        <property name="removeAbandonedTimeout" value="60"/>
        <property name="logAbandoned" value="true" />
        
        <!-- 配置监控统计拦截的filters -->
        <property name="proxyFilters">
            <list>
                <ref bean="stat-filter" />
                <ref bean="wall-filter" />
                <ref bean="log-filter" />
            </list>
        </property>
    </bean>
    
    <bean id="dataSourceSS" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="**" />
        <property name="username" value="test"/>
        <property name="password" value="***"/>
         
        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="1" />
        <property name="minIdle" value="1"/>
        <property name="maxActive" value="8" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="3000"/>
        <!-- 配置间隔多久才进行一次检测(启动destroy线程),检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒;即最多允许一个连接空闲多长时间,超出此时间的连接,会被destroy线程关闭 -->
        <property name="minEvictableIdleTimeMillis" value="300000" />
        <!-- 对空闲接连再被使用时,如果空闲时间超过timeBetweenEvictionRunsMillis,会发出验证sql进行有效检测 -->
        <property name="validationQuery" value="SELECT 'x'" />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <!-- 移除执行超时的sql,单位是毫秒 -->
        <property name="removeAbandoned" value="true"/>
        <property name="removeAbandonedTimeout" value="60"/>
        <property name="logAbandoned" value="true" />
        
        <!-- 配置监控统计拦截的filters -->
        <property name="proxyFilters">
            <list>
                <ref bean="stat-filter" />
                <ref bean="wall-filter" />
                <ref bean="log-filter" />
            </list>
        </property>
    </bean>

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'eimdb.rma_o_customer' doesn't exist

不是很明显的错吗?你的数据库中有rma_o_customer这张表吗? eimdb是数据库schema?还是catalog?

【热门文章】
【热门文章】