Mybatis 多數據源切換

首先在spring下配置多個dataSourcejava

<bean id="masterDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass" value="${master.driverClass}" />
		<property name="jdbcUrl" value="${master.jdbcUrl}" />
		<property name="user" value="${master.user}" />
		<property name="password" value="${master.password}" />
		<property name="minPoolSize" value="${master.minPoolSize}"></property>
		<property name="maxPoolSize" value="${master.maxPoolSize}"></property>
		<property name="maxIdleTime" value="${master.maxIdleTime}"></property>
		<property name="acquireIncrement" value="${master.acquireIncrement}"></property>
		<property name="maxStatements" value="${master.maxStatements}"></property>
		<property name="initialPoolSize" value="${master.initialPoolSize}"></property>
		<property name="idleConnectionTestPeriod" value="${master.idleConnectionTestPeriod}"></property>
		<property name="acquireRetryAttempts" value="${master.acquireRetryAttempts}"></property>
		<property name="breakAfterAcquireFailure" value="${master.breakAfterAcquireFailure}"></property>
		<property name="testConnectionOnCheckout" value="${master.testConnectionOnCheckout}"></property>
		<property name="autoCommitOnClose" value="${master.autoCommitOnClose}"></property>
	</bean>
	

	<bean id="slaveDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass" value="${slave.driverClass}" />
		<property name="jdbcUrl" value="${slave.jdbcUrl}" />
		<property name="user" value="${slave.user}" />
		<property name="password" value="${slave.password}" />
		<property name="minPoolSize" value="${slave.minPoolSize}"></property>
		<property name="maxPoolSize" value="${slave.maxPoolSize}"></property>
		<property name="maxIdleTime" value="${slave.maxIdleTime}"></property>
		<property name="acquireIncrement" value="${slave.acquireIncrement}"></property>
		<property name="maxStatements" value="${slave.maxStatements}"></property>
		<property name="initialPoolSize" value="${slave.initialPoolSize}"></property>
		<property name="idleConnectionTestPeriod" value="${slave.idleConnectionTestPeriod}"></property>
		<property name="acquireRetryAttempts" value="${slave.acquireRetryAttempts}"></property>
		<property name="breakAfterAcquireFailure" value="${slave.breakAfterAcquireFailure}"></property>
		<property name="testConnectionOnCheckout" value="${slave.testConnectionOnCheckout}"></property>
		<property name="autoCommitOnClose" value="${slave.autoCommitOnClose}"></property>
	</bean>

以後自定義一個數據源 算法

<bean id="myDynamicDataSource" class="com.up366.lsp.db.datasource.DynamicDataSource">
		<property name="targetDataSources">
		<!-- 標識符類型 	-->
			<map key-type="java.lang.String">
				<entry key="master" value-ref="masterDataSource"/> 
				<entry key="slave" value-ref="slaveDataSource" />
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="masterDataSource" />
	</bean>

本身寫的自定義數據源 spring

package com.up366.lsp.db.datasource;

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

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDataSouce();
    }

}

以後用線程變量控制sql

package com.up366.lsp.db.datasource;

public class DynamicDataSourceHolder {
    public static final ThreadLocal<String> holder = new ThreadLocal<String>();

    public static void setDataSource(String name) {
        holder.set(name);
    }

    public static String getDataSouce() {
        return holder.get();
    }
    
    public static void clearDataSouce() {    
    	holder.remove();    
    }
    
    public static void setMaster() {
    	DynamicDataSourceHolder.clearDataSouce();
    }
    
    public static void setSlave() {
    	DynamicDataSourceHolder.setDataSource("slave");
    }
}

以後配置一個執行前的aop 動態加載數據源express

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <bean id="manyDataSourceAspect" class="com.up366.lsp.db.datasource.DataSourceAspect" />
    <aop:config>
        <aop:aspect id="c" ref="manyDataSourceAspect">
            <aop:pointcut id="tx" expression="execution(* com.up366.lsp.db.dao.*.*(..))"/>
            <aop:before pointcut-ref="tx" method="before"/>
        </aop:aspect>
    </aop:config>
package com.up366.lsp.db.datasource;

import java.lang.reflect.Method;

import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;

import com.up366.lsp.db.datasource.anno.Master;
import com.up366.lsp.db.datasource.anno.Slave;


public class DataSourceAspect {

	@Autowired
	private SqlSessionFactoryBean sqlSessionFactory;
	
    public void before(JoinPoint point)
    {
        Object target = point.getTarget();
        String method = point.getSignature().getName();

        Class<?>[] classz = target.getClass().getInterfaces();

        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
                .getMethod().getParameterTypes();
        try {
            Method m = classz[0].getMethod(method, parameterTypes);
            if (m != null ) {
            	if(m.isAnnotationPresent(Slave.class)){
            		DynamicDataSourceHolder.setSlave();
            		return ;
            	}
            	if(m.isAnnotationPresent(Master.class)){
            		DynamicDataSourceHolder.setMaster();
            		return ;
            	}
            	//在沒有配置的狀況下走默認
            	String key = classz[0].getName()+"." + m.getName();
            	SqlSessionFactory ss =  sqlSessionFactory.getObject();
            	//獲取類型
            	SqlCommandType type = ss.getConfiguration().getMappedStatement(key,false).getSqlCommandType();
            	//查詢默認從庫
            	if(SqlCommandType.SELECT == type){
            		DynamicDataSourceHolder.setSlave();
            		return ;
            	}
            	//增刪改默認主庫
            	if(type == SqlCommandType.DELETE || SqlCommandType.INSERT == type || SqlCommandType.UPDATE == type)
            	DynamicDataSourceHolder.setMaster();
            }
            
        } catch (Exception e) {
            
        }
    }
	
}

基本上完成了 apache

若是是負載均衡的話 能夠對從庫進行負載多個配置 用算法去肯定session

相關文章
相關標籤/搜索