天天看點

MyBatis多資料源配置

多資料源配置:實作主(Master)從(Slave)庫分離方式,減輕主庫壓力,從庫負責查詢。還有使用中需要用到兩個資料庫時候,使用多資料源配置,可以實作多庫之間切換。

applicationContext.xml

<!-- 配置資料源  Master主-->
	<bean id="dataSourceMaster" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="org.postgresql.Driver"></property>
		<property name="url" value="資料庫位址"></property>
		<property name="username" value="賬戶名"></property>
		<property name="password" value="密碼"></property>
		<property name="maxActive" value="20"/>
        <property name="maxIdle" value="30"/>
        <property name="initialSize" value="1"/>
        <property name="maxWait" value="10000"/>
        <property name="defaultAutoCommit" value="true"/>
        <property name="removeAbandoned" value="true"/>
        <property name="removeAbandonedTimeout" value="60"/>
        <property name="logAbandoned" value="true"/>
	</bean>
	
	<!-- 配置資料源  Slave從庫-->
	<bean id="dataSourceSlave" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="org.postgresql.Driver"></property>
		<property name="url" value="資料庫位址"></property>
		<property name="username" value="帳号"></property>
		<property name="password" value="密碼"></property>
		<property name="maxActive" value="20"/>
        <property name="maxIdle" value="30"/>
        <property name="initialSize" value="1"/>
        <property name="maxWait" value="10000"/>
        <property name="defaultAutoCommit" value="true"/>
        <property name="removeAbandoned" value="true"/>
        <property name="removeAbandonedTimeout" value="60"/>
        <property name="logAbandoned" value="true"/>
	</bean>
	<!-- 資料源 切換 -->	
	<bean id="multipledataSource" class="com.xxx.mobile.datasource.MultipleDataSource"><!-- 注入資料源路由 -->
            <property name="defaultTargetDataSource" ref="dataSourceMaster"/><!-- 預設資料源 -->
            <property name="targetDataSources">
                <map key-type="java.lang.String"><!-- 把主從資料庫添加到map集合 -->
                    <entry key="master" value-ref="dataSourceMaster"/>
                    <entry key="slave" value-ref="dataSourceSlave"/>
                </map>
            </property>
    </bean>
        <!-- Aop 資料源 切換 -->
	<bean id="dataSourceSwitchingAop" class="com.xxx.mobile.datasource.MultipleDataSourceAspectAdvice"/>
	
	<!-- 配置aop -->
	<aop:config>
		<!-- 切換資料源的事務需要放到資料庫事務開啟前執行。針對上述代碼示例中,配置aop時需要指定order(值越小,執行越靠前) -->
	    <aop:aspect id="dataSourceSwitching" ref="dataSourceSwitchingAop" order="0"><!-- 注入資料源路由 dataSourceSwitchingAop-->
            <aop:pointcut id="dataSourceSwitchingService"
                          expression="execution(* com.xxx.mobile.mapper.*.*(..))"/>
            <aop:before method="switchDataSource" pointcut-ref="dataSourceSwitchingService"/>
        </aop:aspect>
	</aop:config>
		
	<!-- 配置Session工廠 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="multipledataSource"></property><!-- 注入 資料源切換 id multipledataSource-->
		<!-- 加載mybatis.cfg.xml檔案 -->
		<property name="configLocation" value="classpath:mybatis.cfg.xml"></property>
		<!-- 自動掃描需要定義類别名的包,将包内的JAVA類的類名作為類别名 -->
		<property name="typeAliasesPackage" value="com.infolink.trade.beans"></property>
	</bean>
           

MultipleDataSource.java

/**
 * 多資料源配置
 * AbstractRoutingDataSource 資料源路由
 * 實作其抽象方法determineCurrentLookupKey(),進而實作對不同資料源的路由功能
 */
public class MultipleDataSource extends AbstractRoutingDataSource{

   //ThreadLocal 保證每個請求都會由一個線程來處理, 是分層系統中共享變量的 進階方式
    private final static ThreadLocal<String> dataSourceKey = new ThreadLocal<String>();

    public static void setDataSourceKey(String dataSource){
        dataSourceKey.set(dataSource);
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return dataSourceKey.get();
    }
}
           

MultipleDataSourceAspectAdvice.java

/**
 * AOP
 * 資料源 轉換
 */
@Component //自動掃描
public class MultipleDataSourceAspectAdvice {
    public void switchDataSource(JoinPoint joinPoint){

        Object object = joinPoint.getTarget();
        DataSourceKey annotation = AnnotationUtils.findAnnotation(object.getClass(),DataSourceKey.class);

        if(null!=annotation){//沒有注解的用預設值
            String value = annotation.value();
            if(null!=value&&value.length()>0){
                MultipleDataSource.setDataSourceKey(value);
            }
        }else{
        	MultipleDataSource.setDataSourceKey("master");
        }

    }

}
注:配置檔案需要配置掃描 和 啟動AOP支援
           

DataSourceKey.java

/**
 * 自定義注解
 * 在mapper包下類或方法上添加自定義注解@DataSourceKey(value="slave") 
 * 進而實作切換資料源到 slave
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceKey {
	String value() default "slave";
}
           

使用時候隻需要在對應類或方法上添加注解,即可實作資料源切換

例:

@MapperScan
       @DataSourceKey(value="slave") //切換資料源
       public interface CardDao {}//類名
           
MyBatis多資料源配置

注::從庫可以多個,主庫預設一個

本文為部落客第一次發文,學習使用過程中整理了一下,歡迎大神們多多提建議、讨論。

繼續閱讀