MyBatis Excutor 拦截器的巧妙用法

 更新时间:2017年10月13日 14:14:40   作者:动力节点  
这里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法,并提供了解决拦截Executor时想要修改MappedStatement时解决并发的问题。感兴趣的朋友一起看看吧

这里要讲的巧妙用法是用来实现在拦截器中执行额外 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,然后去执行。

总结

以上所述是小编给大家介绍的MyBatis Excutor 拦截器的巧妙用法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Spring中的aware接口详情

    Spring中的aware接口详情

    这篇文章主要介绍了Spring中的aware接口详情,Spring中有很多继承于aware中的接口,这些接口到底是做什么用到的,下面我们就一起来看看吧,文章详细内容需要的小伙伴可以参考一下
    2022-05-05
  • Spring boot的上传图片功能实例详解

    Spring boot的上传图片功能实例详解

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。这篇文章主要介绍了Spring boot 上传图片,需要的朋友可以参考下
    2018-03-03
  • 关于Java中Bean的生命周期详解

    关于Java中Bean的生命周期详解

    这篇文章主要介绍了关于Java中Bean的生命周期详解,所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期,需要的朋友可以参考下
    2023-08-08
  • Java如何使用spire进行word文档的替换详解

    Java如何使用spire进行word文档的替换详解

    创作一份文案经常会高频率地使用某些词汇,如地名、人名、人物职位等,若表述有误,就需要整体撤换,下面这篇文章主要给大家介绍了关于Java如何使用spire进行word文档的替换的相关资料,需要的朋友可以参考下
    2023-01-01
  • Java通过正则表达式获取字符串中数字的方法示例

    Java通过正则表达式获取字符串中数字的方法示例

    最近工作中遇到了一个需求,需要利用java获取字符串中的数字,尝试几种方法后发现利用正则表达式实现最为方法,下面这篇文章就主要介绍了Java通过正则表达式获取字符串中数字的方法,文中给出了详细的示例代码,需要的朋友可以参考下。
    2017-03-03
  • 在java中 利用匿名内部类进行较简洁的双括弧初始化的方法

    在java中 利用匿名内部类进行较简洁的双括弧初始化的方法

    本篇文章小编将为大家介绍,关于在java中 利用匿名内部类进行较简洁的双括弧初始化的方法,有需要的朋友可以参考一下
    2013-04-04
  • Java使用FTPClient类读写FTP

    Java使用FTPClient类读写FTP

    这篇文章主要为大家详细介绍了Java使用FTPClient类读写FTP的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • java实现字符串排列组合问题

    java实现字符串排列组合问题

    这篇文章主要为大家详细介绍了java实现字符串排列组合问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • 在java中main函数如何调用外部非static方法

    在java中main函数如何调用外部非static方法

    这篇文章主要介绍了在java中main函数如何调用外部非static方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • java实现识别二维码图片功能

    java实现识别二维码图片功能

    这篇文章主要为大家详细介绍了java实现识别二维码图片功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论