spring整合mybatis多数据源切换

最近项目用到多数据源, 在网上找了资料解决了,稍微描述下.

假如数据源用到两个,一个正式数据库, 一个历史数据库.

在applicationContext.xml中的相关配置如下:

<bean id="dataSource_now" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
	<property name="driverClass" value="${database.driver}"></property>     
	<property name="jdbcUrl" 	 value="${database.url}"></property>
	<property name="user" 		 value="${database.username}"></property> 
	<property name="password" 	 value="${database.password}"></property> 
	<property name="minPoolSize" value="${database.minimumConnectionCount}"></property> 
	<property name="maxPoolSize" value="${database.maximumConnectionCount}"></property> 
	<property name="maxIdleTime" value="${database.houseKeepingSleepTime}"></property> 
</bean>
<!-- 历史库,历史的数据的查询到另外的表进行查询 -->
<bean id="dataSource_his"  class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
	<property name="driverClass" value="${database_his.driver}"></property>     
        <property name="jdbcUrl"     value="${database_his.url}"></property>
        <property name="user" 		 value="${database_his.username}"></property> 
        <property name="password"    value="${database_his.password}"></property> 
        <property name="minPoolSize" value="${database_his.minimumConnectionCount}"></property> 
        <property name="maxPoolSize" value="${database_his.maximumConnectionCount}"></property> 
        <property name="maxIdleTime" value="${database_his.houseKeepingSleepTime}"></property> 
</bean> 

这里相关的配置放在properties文件中加载,就不详述了.数据源的管理和设置默认值.

<bean id="dataSource" class="com.chris.common.multidataSource.DynamicDataSource">   
        <property name="targetDataSources">   
            <map key-type="java.lang.String">   
                <entry key="ds_now" value-ref="dataSource_now" ></entry>   
                <entry key="ds_his" value-ref="dataSource_his" ></entry>   
            </map>   
        </property>   
        <property name="defaultTargetDataSource" ref="dataSource_now"></property>   
</bean>


数据源的管理需要重写AbstractRoutingDataSource类的determineCurrentLookupKey()方法, 这个是最关键的, 他决定了当前线程的绑定事务的上下文.

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author wuxing
 *
 * 2015年2月6日
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
		return DataSourceContextHolder.getDataSourceType();
	}

}

其中DataSourceContextHolder用于获取当前线程的事务上下文.

/**
 * @author wuxing
 *
 * 2015年2月6日
 */
@SuppressWarnings("unchecked")
public class DataSourceContextHolder {   
 
   /**  
    * DataSource上下文,每个线程对应相应的数据源key  
    */  
    @SuppressWarnings("rawtypes")
	public static final ThreadLocal contextHolder = new ThreadLocal();   
       
    public static void setDataSourceType(String dataSourceType)   
    {   
        contextHolder.set(dataSourceType);   
    }   
       
    public static String getDataSourceType()   
    {   
        return (String)contextHolder.get();   
    }   
       
    public static void clearDataSourceType()   
    {   
        contextHolder.remove();   
    }   
}  

setter和getter的参数,就是切换数据源时在配置文件中配置的key..本例中为ds_now和ds_his


这边有个需要注意的地方..当没有调用数据源的set的方法时..不能在之前调用他的get方法.

在ThreadLocal中有段代码, 当get被调用时,若数据源没有被set, 则会调用他的setInitialValue()方法, 而他的initialValue的值为null.

这样的话,系统就会报一行错误--->SqlSession was not registered for synchronization because synchronization is no active.


数据源的和mybatis的配置如下, 指定了mybatis的sql文件的扫描路径.

<bean id="sqlSessionFactory" name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="configLocation" value="classpath:mybatis-config.xml"/>
	<property name="mapperLocations">
		<list>
			<value>classpath:com/chris/dao/impl/mapper/*Mapper.xml</value> 
		</list>
	</property>
</bean>
	
<bean id="sqlSessionFactoryTemplate" name="sqlSessionFactoryTemplate" class="org.mybatis.spring.SqlSessionTemplate">
       <constructor-arg index="0" ref="sqlSessionFactory" />  
</bean>
mybatis-config.xml的配置如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="cacheEnabled" value="true"/>  
		<setting name="lazyLoadingEnabled" value="true"/>  
		<setting name="multipleResultSetsEnabled" value="true"/>  
		<setting name="useColumnLabel" value="true"/>  
		<setting name="useGeneratedKeys" value="true"/>  
		<setting name="defaultExecutorType" value="SIMPLE"/>  
		<setting name="defaultStatementTimeout" value="25000"/>  
	</settings>
</configuration>
接下来就是事务的配置
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
    </bean>   
        <tx:annotation-driven transaction-manager="transactionManager" /> 
    
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value=" com.chris.dao.mapper" />
		<!-- spring 3.1.1 和mybatis 要用名字指定连接工厂 因为跟property-placeholder冲突 -->
		<!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> -->
		<!-- <property name="sqlSessionFactory" ref="sqlSessionFactory" /> -->
		<property name="sqlSessionTemplateBeanName"  value="sqlSessionFactoryTemplate"  />
	</bean>
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*"     propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="del*"     propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="modify*"  propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="update*"  propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="insert*"  propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="txn_*"    propagation="REQUIRED" rollback-for="java.lang.Exception" no-rollback-for=""/> <!-- 需要加事务的函数开头 -->
            <tx:method name="create*"  propagation="REQUIRED" rollback-for="java.lang.Exception" no-rollback-for=""/><!-- 定义不需要回滚的异常 -->
            <tx:method name="*"        read-only="true" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="allManagerMethod" expression="execution(* com.chris.service..*.*(..))" />
        <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" order="10" />
    </aop:config>

通过指定事务内的方法名, 以及事务扫描的包路径,回滚事宜, 将事务配置好.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值