这里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法。
并且会提供一个解决拦截Executor时想要修改MappedStatement时解决并发的问题。
这里假设一个场景:
实现一个拦截器,记录 MyBatis 所有的 insert,update,delete 操作,将记录的信息存入数据库。
这个用法在这里就是将记录的信息存入数据库。
实现过程的关键步骤和代码:
1.首先在某个 Mapper.xml 中定义好了一个往日志表中插入记录的方法,假设方法为id="insertSqlLog"。
2.日志表相关的实体类为SqlLog.
3.拦截器签名:
@Intercepts({@org.apache.ibatis.plugin.Signature( type=Executor.class, method="update", args={MappedStatement.class, Object.class})}) public class SqlInterceptor implements Interceptor
4.接口方法简单实现:
public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); MappedStatement ms = (MappedStatement) args[0]; Object parameter = args[1]; SqlLog log = new SqlLog(); Configuration configuration = ms.getConfiguration(); Object target = invocation.getTarget(); StatementHandler handler = configuration.newStatementHandler((Executor) target, ms, parameter, RowBounds.DEFAULT, null, null); BoundSql boundSql = handler.getBoundSql(); //记录SQL log.setSqlclause(boundSql.getSql()); //执行真正的方法 Object result = invocation.proceed(); //记录影响行数 log.setResult(Integer.valueOf(Integer.parseInt(result.toString()))); //记录时间 log.setWhencreated(new Date()); //TODO 还可以记录参数,或者单表id操作时,记录数据操作前的状态 //获取insertSqlLog方法 ms = ms.getConfiguration().getMappedStatement("insertSqlLog"); //替换当前的参数为新的ms args[0] = ms; //insertSqlLog 方法的参数为 log args[1] = log; //执行insertSqlLog方法 invocation.proceed(); //返回真正方法执行的结果 return result; }
重点
MappedStatement是一个共享的缓存对象,这个对象是存在并发问题的,所以几乎任何情况下都不能去修改这个对象(通用Mapper除外),想要对MappedStatement做修改该怎么办呢?
并不难,Executor中的拦截器方法参数中都有MappedStatement ms,这个ms就是后续方法执行要真正用到的MappedStatement,这样一来,问题就容易解决了,根据自己的需要,深层复制MappedStatement对象中自己需要修改的属性,然后修改这部分属性,之后将修改后的ms通过上面代码中args[0]=ms这种方式替换原有的参数,这样就能实现对ms的修改而且不会有并发问题了。
这里日志的例子就是一个更简单的应用,并没有创建ms,只是获取了一个新的ms替换现有的ms,然后去执行。
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整