redis读写分离 java_Java读写分离实现

该博客介绍了一个名为DynamicDataSourceInterceptor的Java插件,用于在MyBatis中实现读写分离。插件通过拦截Executor的update和query方法,根据SQL命令类型(如SELECT, INSERT, UPDATE, DELETE)来判断是否在事务中以及操作类型,从而决定使用主库还是从库。当事务不活跃时,SELECT操作会选择从库,而增删改操作或在事务中则选择主库。" 123618766,2799809,低代码探秘:从计算机视觉到移动应用,"['Azure', 'RPA', '低代码开发', 'PaaS', '移动应用开发']
摘要由CSDN通过智能技术生成

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

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值