Java Mybatis实现主从同步

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

public class DynamicDataSource extends AbstractRoutingDataSource{

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

  

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

public class DynamicDataSourceHolder {
	private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceHolder.class);
    private static ThreadLocal<String> contextHolder=new ThreadLocal<String>();//保证线程安全
    public static final String DB_MASTER="master";
    public static final String DB_SLAVE="slave";
    public static String getDbType(){
    	String db=contextHolder.get();
    	if(db==null){
    		db=DB_MASTER;
    	}
    	return db;
    }
    public static void setDbType(String str){
    	logger.debug("所使用的数据源为:"+str);
    	contextHolder.set(str);
    }
    //清理连接类型
    public static void clearDBType(){
    	contextHolder.remove();
    }
    
}

  

import java.util.Locale;
import java.util.Properties;
import java.util.concurrent.Executor;

import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * @author wls
 *
 */

@Intercepts({@Signature(type=Executor.class,method="update",args={MappedStatement.class,Object.class}),
@Signature(type=Executor.class,method="query",args={MappedStatement.class,Object.class,
RowBounds.class,ResultHandler.class})})

public class DynamicDataSourceInterceptor implements Interceptor{
	private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceInterceptor.class);
	private static final String REGEX=
			".*insert\\u0020.*|.*delete\\u0020.*|.8update\\u0020.*";

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		//判断当前是不是事物
		boolean synchronizatioinActive=TransactionSynchronizationManager.
				isActualTransactionActive();
		Object[] objects= invocation.getArgs();
		MappedStatement ms=(MappedStatement)objects[0];
		String lookupKey=DynamicDataSourceHolder.DB_MASTER;
		if(synchronizatioinActive!=true){
			
			//读方法
			if(ms.getSqlCommandType().equals(SqlCommandType.SELECT)){
				//SELECT_KEY为自增id查询主键SELECT LAST_INSERT_ID(),使用主库
				if(ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)){
					lookupKey=DynamicDataSourceHolder.DB_MASTER;
				}else{
					BoundSql boundSql=ms.getSqlSource().getBoundSql(objects[1]);
					String sql=boundSql.getSql().toLowerCase(Locale.CHINA).
							replaceAll("[\\t\\n\\r]", " ");
					if(sql.matches(REGEX)){
						lookupKey=DynamicDataSourceHolder.DB_MASTER; //增删改
					}else{
						lookupKey=DynamicDataSourceHolder.DB_SLAVE; //查,从库
					}
				}
			}			
		}
		else{
			lookupKey=DynamicDataSourceHolder.DB_MASTER;
		}
logger.debug("设置方法[{}] use[{}]Strategy,SqlCommanType[{}]" ,ms.getId(),lookupKey,
		ms.getSqlCommandType().name());;
		DynamicDataSourceHolder.setDbType(lookupKey);
		return invocation.proceed();
	}

	@Override  //返回封装好的对象
	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		if(target instanceof Executor){
			return Plugin.wrap(target, this);
		}else{
			return target;
		}
	}

	@Override
	public void setProperties(Properties arg0) {
		// TODO Auto-generated method stub
		
	}
}

  配置:

 

 mybatis配置:

<plugins>
	<plugin interceptor="split.DynamicDataSourceInterceptor"></plugin>
	</plugins>

  

posted @ 2019-04-01 17:02  石shi  阅读(507)  评论(0编辑  收藏  举报