MyBatis Excutor 拦截器的巧妙用法

这里要讲的巧妙用法是用来实现在拦截器中执行额外 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 拦截器的巧妙用法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • MyBatis拦截器实现分页功能实例

    由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能 现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践 既然是基于MyBatis 所以就先搭建一个Mybatis的小项目 1.01导入 mybatis和mysql的包 1.02.配置文件 Configuration.xml 中添加 <environments default="development"&

  • MyBatis拦截器:给参数对象属性赋值的实例

    该拦截器的作用:在进行增加.修改等操作时,给数据模型的一些通用操作属性(如:创建人.创建时间.修改人.修改时间等)自动赋值. 该实现是在DAO层拦截,即存入DB前最后一层.后经分析,不是很合理,改为在service层拦截,用spring AOP来实现了,该代码遂弃用.不过已经测试可用,记录备忘. package com.development; import java.lang.reflect.InvocationTargetException; import java.util.Date; i

  • Mybatis拦截器的实现介绍

     MyBatis介绍 MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .它支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的

  • Mybatis拦截器实现分页

    最终dao层结果: public interface ModelMapper { Page<Model> pageByConditions(RowBounds rowBounds, Model record); } 接下来一步一步来实现分页. 一.创建Page对象: public class Page<T> extends PageList<T> { private int pageNo = 1;// 页码,默认是第一页 private int pageSize = 1

  • java利用mybatis拦截器统计sql执行时间示例

    可以根据执行时间打印sql语句,打印的sql语句是带参数的,可以拷贝到查询分析器什么的直接运行 复制代码 代码如下: package mybatis; import java.text.DateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.Properties; import org.apache.ibatis.executor.Executor;import

  • MyBatis Excutor 拦截器的巧妙用法

    这里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法. 并且会提供一个解决拦截Executor时想要修改MappedStatement时解决并发的问题. 这里假设一个场景: 实现一个拦截器,记录 MyBatis 所有的 insert,update,delete 操作,将记录的信息存入数据库. 这个用法在这里就是将记录的信息存入数据库. 实现过程的关键步骤和代码: 1.首先在某个 Mapper.xml 中定义好了一个往日志表中插入记录的方法,假设方法为id="insert

  • mybatis 通过拦截器打印完整的sql语句以及执行结果操作

    开发过程中,如果使用mybatis做为ORM框架,经常需要打印出完整的sql语句以及执行的结果做为参考. 虽然mybatis结合日志框架可以做到,但打印出来的通常都是sql和参数分开的. 有时我们需要调试这条sql的时候,就需要把参数填进去,这样未免有些浪费时间. 此时我们可以通过实现mybatis拦截器来做到打印带参数的完整的sql,以及结果通过json输出到控制台. 直接看代码和使用方法吧: MyBatis拦截器打印不带问号的完整sql语句拦截器 import java.text.DateF

  • Mybatis中拦截器的简单实现方法

    前言 需求驱动学习,最近一周组长让我在业务模块里加日志,经过与导师以及组长讨论决定用拦截器记录日志.周五下班前已经发了提测邮件. 虽然我知道 MyBatis 有这东西,但是没在实际情况中用过,心里有点虚2333--所以才有了此文的理解. 前世今生 它的本质就是 JDK 的动态代理.首先先来复习一下动态代理我贴了一段最常见的 JDK 动态代理的代码 //服务员的接口 public interface Waiter { void serve(); } //服务员的实现 public class Wa

  • Mybatis Plugin拦截器开发过程详解

    这篇文章主要介绍了Mybatis Plugin拦截器开发过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.Plugin MyBatis 允许使用插件来拦截的方法调用包括: • Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed) • ParameterHandler (getParameterObject,

  • Mybatis自定义拦截器和插件开发详解

    前言 在Spring中我们经常会使用到拦截器,在登录验证.日志记录.性能监控等场景中,通过使用拦截器允许我们在不改动业务代码的情况下,执行拦截器的方法来增强现有的逻辑.在mybatis中,同样也有这样的业务场景,有时候需要我们在不侵入原有业务代码的情况下拦截sql,执行特定的某些逻辑.那么这个过程应该怎么实现呢,同样,在mybatis中也为开发者预留了拦截器接口,通过实现自定义拦截器这一功能,可以实现我们自己的插件,允许用户在不改动mybatis的原有逻辑的条件下,实现自己的逻辑扩展. 本文将按

  • springboot整合mybatis分页拦截器的问题小结

    简介 又到了吹水时间,是这样的,今天开发时想将自己写好的代码拿来优化,因为不想在开发服弄,怕搞坏了到时候GIT到生产服一大堆问题,然后把它分离到我轮子(工具)项目上,最后运行后发现我获取List的时候很卡至少10秒,我惊了平时也就我的正常版本是800ms左右(不要看它很久,因为数据量很大,也很正常.),前提是我也知道很慢,就等的确需要优化时,我在放出我优化的plus版本,回到10秒哪里,最开始我刚刚接到这个app项目时,在我用 PageHelper.startPage(page, num);(分

  • SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

    目录 SpringBoot整合Mybatis自定义拦截器不起作用 1. 原始的读取mybatis-config.xml文件 2. 与SpringBoot容器整合 2.1 mybatis的自动装载 3. 在mybatis-config.xml配置又放入Spring容器 SpringBoot 自定义Mybatis拦截器 第一种 第二种 第三种 SpringBoot整合Mybatis自定义拦截器不起作用 Mybatis插件生效的方式: 1. 原始的读取mybatis-config.xml文件 该方式和

  • 在springboot中如何给mybatis加拦截器

    目录 1.实现Interceptor接口,并添加拦截注解 @Intercepts 1.在mybatis中可被拦截的类型有四种(按照拦截顺序) 2.各个参数的含义 2.在配置文件中添加拦截器 (1)第一种 (2)第二种 (3)第三种 拦截器的作用就是我们可以拦截某些方法的调用,在目标方法前后加上我们自己逻辑 Mybatis拦截器设计的一个初衷是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑. mybatis 自定义拦截器 1.实现Interceptor 接口,并添加拦截注

  • Mybatis Interceptor 拦截器的实现

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件. 拦截器(Interceptor)在 Mybatis 中被当做插件(plugin)对待,官方文档提供了 Executor,ParameterHandler,ResultSetHandler,StatementHandler 共4种,并且提示"这些类中方法的细

  • Spring interceptor拦截器配置及用法解析

    fifter.servlet.interceptor fifter用来处理请求头.请求参数.编码的一些设置,然后转交给servlet,处理业务,返回 servlet现在常用的spring,servlet拦截/到DispatcherServlet,交由spring管理 interceptor,servlet请求之后可以实现HandlerInterceptor做到preHandle.postHandle.afterCompletion在controller之前.之后.渲染之后 登陆 业务中常用的登陆

随机推荐