Mybatis拦截器

Stella981
• 阅读 573

1.介绍 : 

  我自己理解中的mybatis拦截器,和普通拦截器一样,在执行一段程序之前对其做一些特殊处理,网上一般都是用其做分页处理、日志记录...,实现原理就是在预处理前对其进行一些处理

2.简单说明:

  mybatis提供了一个Interceptor接口,方便扩展所需的操作

  Object intercept(Invocation invocation)

  Object plugin(Object target)

void setProperties(Properties properties)

我们所需实现的便是以上的三个方法,先对每个方法有个大致了解

2.1 先说setProperties方法,我们在mybatis.xml配置文件中有一个plugins标签,其中的一个plugin标签对应着一个Interceptor实现类。在plugin标签下,含有property标签用于存放一些我们可修改的配置信息

举个例子,mysql、sqlServer、oracle他们sql分页的语句都有一定的区别,所以为了区分,我们便可以使用此配置(这个不是重点,其他两个才是)

2.2 plugin决定我们是否要拦截,拦截条件是什么,返回的是一个什么样的对象

2.3 intercept方法就是拦截期间我们所做的操作

3.实现过程 :

3.1 首先封装一个分页数据对象,最少3个参数(页码、每页记录数、起始记录数(算出来的))

3.2 创建一个实现Interceptor接口的对象,添加注解@Intercepts和@Signature,这里有两个重点

3.2.1 我们如何使用这两个注解?

@Signature注解信息更加具体,相当于集合的一个元素,@Intercepts就相当于集合了

@Signature包含三个参数:(这样就具体的定位了)

method : 表示拦截的方法

type :表示拦截的类,Executor、StatementHandler、ParameterHandler和ResultSetHandler这四个接口的实现类

args:表示方法参数

例如:@Intercepts( {@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class,  ResultHandler.class }),

                @Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class}) })

3.2.2 如何读取注解信息?

上文说到plugin指定在什么地方拦截,那么此方法就需要识别这两个注解。当然提供两个注解的是Mybatis,那么mybatis肯定也有解析这两个注解的类,

       Plugin里面有一个静态方法wrap(Object target,Interceptor interceptor)。所以一般plugin里面只要写Plugin.wrap(target,this);就可以了

  3.3 忘了说一点,我们setProperties是最先执行的,所以我们需要预先定义变量来保存配置参数

  3.4 已经拦截了,那么我们先获取当前拦截类,读取拦截类信息,再进行下一步操作(具体案例来分析)

利用拦截器实现Mybatis分页的原理: 
 * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 
 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 
 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 
 * StatementHandler对象的prepare方法,即调用invocation.proceed()。

    //对于StatementHandler其实只有两个实现类,一个是RoutingStatementHandler,另一个是抽象类BaseStatementHandler,  
       //BaseStatementHandler有三个子类,分别是SimpleStatementHandler,PreparedStatementHandler和CallableStatementHandler,  
       //SimpleStatementHandler是用于处理Statement的,PreparedStatementHandler是处理PreparedStatement的,而CallableStatementHandler是  
       //处理CallableStatement的。Mybatis在进行Sql语句处理的时候都是建立的RoutingStatementHandler,而在RoutingStatementHandler里面拥有一个  
       //StatementHandler类型的delegate属性,RoutingStatementHandler会依据Statement的不同建立对应的BaseStatementHandler,即SimpleStatementHandler、  
       //PreparedStatementHandler或CallableStatementHandler,在RoutingStatementHandler里面所有StatementHandler接口方法的实现都是调用的delegate对应的方法。  
       //我们在PageInterceptor类上已经用@Signature标记了该Interceptor只拦截StatementHandler接口的prepare方法,又因为Mybatis只有在建立RoutingStatementHandler的时候  
       //是通过Interceptor的plugin方法进行包裹的,所以我们这里拦截到的目标对象肯定是RoutingStatementHandler对象。

    上述内容都来自于 http://elim.iteye.com/blog/1851081?page=2#comments (详细请观看这个博客)

    3.4.1 RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();//用来获取当前拦截类

    拦截之后我们需要知道接下来该做什么,这又是另一个话题了,这里说个题外话,我觉得MySql可能并不太需要这部分的处理,limit函数友好的帮我们处理了这一类问题

@——@以上信息纯属胡说八道

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
MyBatis拦截器实现分页
MyBatis分页拦截器实现前言    拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。打个比
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
2年前
Mybatis拦截器分析
【基本思路】拦截器在哪里拦截?什么情况下才会拦截代理?怎么代理呢?只要搞清楚这些,基本的拦截器功能也3拦截器实现原理mybatis支持拦截器,实现的原理就是利用JDK的动态代理。拦截器在哪里呢?mybatis到底提供几处可以拦截呢?请看下图,通过分析源码可知基本查询流程如下:!mybatis的interceptor拦截器流程图(http:
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这