importjava.util.Locale;importjava.util.Properties;importorg.apache.ibatis.executor.Executor;importorg.apache.ibatis.executor.keygen.SelectKeyGenerator;importorg.apache.ibatis.mapping.BoundSql;importorg.apache.ibatis.mapping.MappedStatement;importorg.apache.ibatis.mapping.SqlCommandType;importorg.apache.ibatis.plugin.Interceptor;importorg.apache.ibatis.plugin.Intercepts;importorg.apache.ibatis.plugin.Invocation;importorg.apache.ibatis.plugin.Plugin;importorg.apache.ibatis.plugin.Signature;importorg.apache.ibatis.session.ResultHandler;importorg.apache.ibatis.session.RowBounds;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.transaction.support.TransactionSynchronizationManager;
@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 implementsInterceptor {private static Logger logger = LoggerFactory.getLogger(DynamicDataSourceInterceptor.class);private static final String REGEX = ".*insert\\u0020.*|.*delete\\u0020.*|.*update\\u0020.*";
@Overridepublic Object intercept(Invocation invocation) throwsThrowable {//判断当前是不是事务
boolean synchronizationActive =TransactionSynchronizationManager.isActualTransactionActive();//获取crud操作的参数
Object[] objects =invocation.getArgs();//获取第一个参数可以知道,具体是crud哪个操作
MappedStatement ms = (MappedStatement) objects[0];
String lookupKey=DynamicDataSourceHolder.DB_MASTER;if (synchronizationActive != true) {//读方法
if(ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {//selectKey 为自增id查询主键(SELECT LAST_INSERT_ID())方法,使用主库
if(ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)) {
lookupKey=DynamicDataSourceHolder.DB_MASTER;
}else{//获取第二个参数,即sql
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);returninvocation.proceed();
}//若是Excutor就拦截下来
@OverridepublicObject plugin(Object target) {//拦截Executor是因为,Execuror支持一系列增删改查
if (target instanceofExecutor) {return Plugin.wrap(target, this);
}else{returntarget;
}
}
@Overridepublic voidsetProperties(Properties arg0) {//TODO Auto-generated method stub
}
}