SpringMVC+mybatis动态切换数据源,多数据库语言databaseId无效怎么解决。

1、采用SpringMVC+mybatis
2、动态切换数据源实现,单独测试有效

 public class DataSources extends AbstractRoutingDataSource{  
    @Override  
    protected Object determineCurrentLookupKey() {  
        return DataSourceSwitch.getDataSourceType();  
    }  
}  

3、Mybatis不同数据库语言支持实现,单独测试有效

 <!--支持多类型数据库配置-->
    <bean id="vendorProperties"
          class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="Oracle">oracle</prop>
                <prop key="MySQL">mysql</prop>
            </props>
        </property>
    </bean>
    <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
        <property name="properties" ref="vendorProperties" />
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource" />
        <property name="databaseIdProvider" ref="databaseIdProvider" />
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        …………

            <select id="getTime" resultType="java.lang.String" databaseId="oracle">
          select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
    </select>

    <select id="getTime" resultType="java.lang.String" databaseId="mysql">
          select now()
    </select>

4、动态切换数据源之后再访问带有databaseId的dao方法就无效了。

5、看SqlSessionFactoryBean源码,databaseId相关代码如下

 if (this.databaseIdProvider != null) {
            try {
                configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
            } catch (SQLException var24) {
                throw new NestedIOException("Failed getting a databaseId", var24);
            }
        }

                 public String getDatabaseId(DataSource dataSource) {
        if (dataSource == null) {
            throw new NullPointerException("dataSource cannot be null");
        } else {
            try {
                return this.getDatabaseName(dataSource);
            } catch (Exception var3) {
                log.error("Could not get a databaseId from dataSource", var3);
                return null;
            }
        }
    }

断点跟踪代码,只有启动服务的时候执行一次,切换数据源不执行,跪求求高手告知解决办法。献出全部C币。

http://blog.csdn.net/paditang/article/details/78297702 你看看这篇文章能不能帮到你。
以下是mybatis的配置,其他和hibernate相同

 <?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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

        <bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>    
        <!--initialSize: 初始化连接-->  
        <property name="initialSize" value="5"/>  
        <!--maxIdle: 最大空闲连接-->  
        <property name="maxIdle" value="15"/>  
        <!--minIdle: 最小空闲连接-->  
        <property name="minIdle" value="5"/>  
        <!--maxActive: 最大连接数量-->  
        <property name="maxActive" value="20"/> 
        <property name="minEvictableIdleTimeMillis" value="18000000"/> 
        <!--removeAbandoned: 是否自动回收超时连接-->  
        <property name="removeAbandoned" value="true"/>  
        <!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->  
        <property name="removeAbandonedTimeout" value="180"/>  
        <!--maxWait: 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒-->  
        <property name="maxWait" value="3000"/>  
        <property name="validationQuery">  
        <value>SELECT 1</value>  
        </property>  
        <property name="testOnBorrow">  
        <value>true</value>  
        </property> 
    </bean>

    <bean parent="parentDataSource" id="db_record_read">
        <property name="url" value="${jdbc.url.read}"/>
        <property name="username" value="${jdbc.username.read}"/>  
        <property name="password" value="${jdbc.password.read}"/>  
    </bean>

    <bean parent="parentDataSource" id="db_record_write">
        <property name="url" value="${jdbc.url.write}"/>
        <property name="username" value="${jdbc.username.write}"/>  
        <property name="password" value="${jdbc.password.write}"/>  
    </bean>

    <bean parent="parentDataSource" id="db_vehicle">
        <property name="url" value="${jdbc.url.vehicle}"/>
        <property name="username" value="${jdbc.username.vehicle}"/>  
        <property name="password" value="${jdbc.password.vehicle}"/>  
    </bean>

    <bean parent="parentDataSource" id="db_admin">
        <property name="url" value="${jdbc.url.admin}"/>
        <property name="username" value="${jdbc.username.admin}"/>  
        <property name="password" value="${jdbc.password.admin}"/>  
    </bean>


    <bean class="com.xx.config.datasource.DynamicDataSource" id="dataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry value-ref="db_record_read" key="db_record_read"></entry>
                <entry value-ref="db_record_write" key="db_record_write"></entry>
                <entry value-ref="db_vehicle" key="db_vehicle"></entry>
                <entry value-ref="db_admin" key="db_admin"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="db_record_read"></property>
    </bean>

    <!-- 获取MyBatis sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
        p:dataSource-ref="dataSource"
        p:configLocation="classpath:myBatisConf.xml"
        p:mapperLocations="classpath:com/xx/mapping/*.xml"><!-- 扫描Mapper文件 -->
         <property name="plugins">
            <array>
              <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                  <!--使用下面的方式配置参数,一行配置一个 -->
                  <value>
                    helperDialect=MySql
                  </value>
                </property>
              </bean>
            </array>
         </property>
    </bean>



    <!-- 扫描直接使用mapper接口类操作dao -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"     
        p:basePackage="com.xx.mapping">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

问题已经初步解决了。
原因是因为mybatis的SqlSessionFactoryBean只在spring配置文件第一次加载的时候初始化,动态切换数据源之后并没有通知SqlSessionFactoryBean
修改databaseId为当前数据源,所以依旧使用默认数据源执行sql。
解决办法:
1、跟踪源码发现SqlSessionFactoryBean提供了修改databaseId的方法,如下

  if (this.databaseIdProvider != null) {
            try {
                **configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));**
            } catch (SQLException var24) {
                throw new NestedIOException("Failed getting a databaseId", var24);
            }
        }
 configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));//修改databaseId

2、通过sqlSessionFactoryBean.getObject().getConfiguration()可获取到configuration对象。
3、sqlSessionFactoryBean是Spring初始化的bean。
4、切换数据源之后调用修改databaseId即可。

配置了几个SqlSessionFactory实例呢? 一个的话,你这样修改了Configuration对象的的databaseId的话,对使用其他数据源的代码没有影响吗?