首页 > 其他分享 >MyBatis插件原理解析(转载)

MyBatis插件原理解析(转载)

时间:2023-04-04 09:35:36浏览次数:33  
标签:插件 自定义 pageSize update Mybatis MyBatis 解析

前言

大多数框架都支持插件,用户可通过编写插件来自行扩展功能,Mybatis也不例外。

在Mybatis中最出名的就是PageHelper 分页插件,下面我们先来使用一下这个分页插件。

如何集成分页插件

Spring-Boot+Mybatis+PageHelper

引入pom依赖

<dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper-spring-boot-starter</artifactId>
   <version>1.2.3</version>
</dependency>

配置分页插件配置项

pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql

service接口代码

PageInfo selectUsersByName(int pageIndex, int pageSize);

service实现类代码

@Override
public PageInfo selectUsersByName(int pageIndex, int pageSize) {
    PageHelper.startPage(pageIndex, pageSize);
    List<User> users = userMapper.selectUsersByName(null);
    return new PageInfo(users);
}

mapper代码

<select id="selectUsersByName" resultMap="User">
    select * from m_user
    <where>
        <if test="userName != null and userName != ''">
            `name` = #{userName}
        </if>
    </where>
</select>
List<User> selectUsersByName(@Param("userName") String userName);

controller代码

@GetMapping("/user/name")
public PageInfo selectUsersByName(int pageIndex, int pageSize) {
    return userService.selectUsersByName(pageIndex, pageSize);
}

然后我们访问

http://localhost:9002/user/name?pageIndex=1&pageSize=10

输出结果:

输出重要项说明:

  • pageNum:当前页码。
  • pageSize:每页数。
  • list:就是我们返回的业务数据。
  • total:总数据。
  • hasNextPage:是否存在下一页。

我们在看看输出SQL:

发现其实执行了两条SQL:count和limit。

猜测分页插件实现

1.这个分页插件无非就是在我们的查询条件上拼接了个limit和做了一个count查询。

2.我们这里使用的是Mysql作为数据库,如果是Oracle的话那就不是limit了,所以这里有多重数据库对应的方案。

3.拦截并做了sql和相关处理。

根据官网快速入门插件

下面是来自官网的一段话:

MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。这些都是更底层的类和方法,所以使用插件的时候要特别当心。

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

那我们就尝试着按照官方来写一个插件。

自定义插件

@Intercepts({@Signature(
        type= Executor.class,
        method = "update",
        args = {MappedStatement.class,Object.class})})
public class TianPlugin implements Interceptor {
    private Properties properties = new Properties();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("老田写的一个Mybatis插件--start");
        Object returnObject = invocation.proceed();
        System.out.println("老田写的一个Mybatis插件---end");
        return returnObject;
    }
}

然后把插件类注入到容器中。

这里的自定义完全是官网给出的案例。从自定义的插件类中看到有个update,我们猜测肯定是需要执行update才会被拦截到。

访问前面的代码:http://localhost:9002/updateUser

成功了。

这是大家肯定会联想到我们刚刚开始学动态代理的时候,不就是在要调用的方法的前面和后面做点小东东吗?

Mybatis的插件确实就是这样的。

我们来分析一下官方的那段话和我们自定义的插件。

分析

首先,我们自定义的插件必须是针对下面这四个类以及方法。

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

其次,我们必须实现Mybatis的Interceptor。

Interceptor中三个方法的作用:

  • intercept():执行拦截内容的地方,比如:在调用某类方法前后做一些自己的处理,简单就是打印日志。
  • plugin():决定是否触发intercept()方法。
  • setProperties():给自定义的拦截器传递我们配置的属性参数(这个可以暂时不管他,后面我们写一个相对完整点的插件,你就明白是干啥的了)。

 

 

 

 

标签:插件,自定义,pageSize,update,Mybatis,MyBatis,解析
From: https://www.cnblogs.com/grassLittle/p/17285214.html

相关文章

  • Sevlet规范:HttpServlet类 和 HttpServletRequest接口 源码解析
    Sevlet规范:HttpServlet类和HttpServletRequest接口源码解析每博一文案命运总是不如人愿,但往往是在无数的痛苦总,在重重的矛盾和艰辛中,才是人成熟起来。你,为这瞬间的辉煌,忍耐了多少暗淡无光的日月,你会死亡,但你也会证明生命有多强大。一次邂逅,一次目光的交融,就是永远的合二为......
  • 【AGC】引入AGC插件SDK后应用出现中文名乱码问题
    【关键字】AGC、android、插件 【问题描述】开发者反馈应用集成了AGCAppLinking服务,在引入AGC插件时遇到了一些问题。引入AGC插件后应用的中文名出现乱码的问题,具体如下所述:在应用级的build.gradle中引入com.huawei.agconnect后应用中文名乱码1.在android/app/build.gradl......
  • 如何通过MyBatis的插件功能来实现分表功能
    前言之前项目中由于几张表的数据量特别的大,在查询的时候特别耗时,所以决定对其进行分表处理。考虑到项目中用的MyBatis作为ORM框架,所以便决定使用它的插件功能来实现动态的替换查询的表来实现分表功能。功能实现整体的目录结构如下TableShard:注解,用来标记需要分表的接口或者......
  • 解析: xpath
    解析_1_xpath基本使用<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><title>Title</title></head><body><ul><liid="l1"class="c1&q......
  • (4.3)数组、对象及类数组对象,set的用法,正则表达式的常用方法,蓝桥杯备赛-(生成数组、数
    1.1数组、对象及类数组对象1.数组:​ 数组是有序的数据集合,其中的索引值从0开始递增,并且数组有length属性,可以获取数组内的元素个数,其中的值可以是任何的数组类型。2.对象:​ 对象是无序的是由一个或多个键值对组成的数据集合,对象没有length属性。3.伪数组(类数组对象):​ ......
  • 设计模式(三十一)----综合应用-自定义Spring框架-自定义Spring IOC-定义解析器、IOC容
    3定义解析器相关类3.1BeanDefinitionReader接口BeanDefinitionReader是用来解析配置文件并在注册表中注册bean的信息。定义了两个规范:获取注册表的功能,让外界可以通过该对象获取注册表对象。加载配置文件,并注册bean数据。/***@versionv1.0*@ClassName:BeanDe......
  • mybatis调用存储过程,并返回out参数
        ......
  • Mybatis-Plus代码生产器
    【问题描述】在微服务的开发过程中,每次新创建一个微服务项目的时候,都需要手工添加controller、service、entity和mapper文件夹和文件时会比较麻烦,并且增加不少的工作量。是否有一个模块,可以自动生成对应的目录和文件呢?真的有这样的代码生产器文件:一、使用之前先确认POM文件中下......
  • EasyCVR插件工具:如何删除EasyShark的抓包数据?
    在前期的文章中,我们分享了关于EasyCVR平台新增的插件工具,感兴趣的用户可以查看这篇文章:《EasyCVR视频融合平台开放插件功能:支持EasyNTS与EasyShark》。其中,EasyShark是用于抓包的工具,支持在客户端直接抓包查看服务器的SIP消息。但是,有用户反馈,由于经常抓包产生了大量的数据,不知道如......
  • 软件加壳输入表处理-解析
    本篇博文说下PE文件中输入表的格式和具体的使用,以及在软件加壳中的注意事项(本人菜鸟),高手飘过IMAGE_IMPORT_DESCRIPTORSTRUC{unionCharacteristicsDWORDOriginalFirstThunkDWORDendsTimeDateStampDWORDForwardChainDWORDNameD......