首页 > 其他分享 >SpringBoot 适配 MyBatis 分页插件功能(自定义拦截器方式)

SpringBoot 适配 MyBatis 分页插件功能(自定义拦截器方式)

时间:2022-12-03 10:06:36浏览次数:68  
标签:插件 分页 pageSize int 适配 mybatis currentPage public 自定义


文章目录

  • ​​1. 自定义分页插件​​
  • ​​1.1. application.properties 添加 mybatis 属性​​
  • ​​1.2. mybatis-config.xml 配置文件​​
  • ​​1.3. 分页拦截器类 PagePlugin​​
  • ​​1.4. 分页对象实体类 PageInfo​​
  • ​​1.5. mapper 文件 SQL 配置信息​​
  • ​​1.6. 实际项目中使用​​
  • ​​2. 使用 Github 开源分页插件​​

MyBatis 分页插件原理: 通过拦截器拦截指定方法重写响应SQL语句实现

1. 自定义分页插件

 

1.1. application.properties 添加 mybatis 属性

# Locations of MyBatis mapper files. 
mybatis.mapper-locations=classpath*:/mybatis/mapper/**.xml

# Packages to search type aliases. (Package delimiters are ",; \t\n")
mybatis.type-aliases-package=com.answer.springboot.mybatis.web.entity

# Location of MyBatis xml config file.
mybatis.config-location=classpath:/mybatis/config/mybatis-config.xml

 

1.2. mybatis-config.xml 配置文件

<configuration>
<!-- 引入 MyBatis 分页插件 -->
<plugins>
<plugin interceptor="com.answer.springboot.mybatis.web.util.paging.PagePlugin">
<!-- 数据库方言 -->
<property name="dialect" value="mysql" />
<!-- 拦截以 Page 结尾的所有方法 -->
<!--<property name="pageSqlId" value=".*(Page)$" />-->
<!-- 拦截以 find 开头的所有方法 -->
<property name="pageSqlId" value="^find.*" />
<!-- 分页对象信息对应的key值 -->
<property name="pageParam" value="pageInfo" />
</plugin>
</plugins>
</configuration>

 

1.3. 分页拦截器类 PagePlugin

// type : 可拦截的类型: Executor、StatementHandler、ParameterHandler 和 ResultSetHandler
// 不同类型拦截器的顺序 Executor -> ParameterHandler -> StatementHandler ->ResultSetHandler
// 拦截 StatementHandler#prepare 方法, args 为方法 prepare 的参数
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class}) })
public class PagePlugin implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(PagePlugin.class);

/** 数据库方言 */
private static String dialect = "mysql";
/** 拦截以 Page 结尾的所有方法 */
private static String pageSqlId;
/** 分页对象信息对应的key值 */
private static String pageParam;

@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
// 获取查询接口映射的相关信息
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
// 获取方法的全限定名, 或者通过boundSql.getParameterObject()获取
String methodAllName = mappedStatement.getId();
// 截取方法名
String methodName = methodAllName.substring(methodAllName.lastIndexOf(".") + 1, methodAllName.length());
// 获取方法的类型
SqlCommandType sqlCmdType = mappedStatement.getSqlCommandType();
// 如果是查询SQL并且和 pageSqlId 匹配则进行拦截, 进行统一的分页处理
if (SqlCommandType.SELECT == sqlCmdType && methodName.matches(pageSqlId)) {
// 获取方法的参数信息
Map paramsMap = (Map) statementHandler.getParameterHandler().getParameterObject();
// 如果参数中包含分页对象信息, 则进行重写SQL
if (paramsMap.containsKey(pageParam)) {
// 分页信息实体类
PageInfo pageInfo = (PageInfo) paramsMap.get(pageParam);
// 当前页码
int currentPage = pageInfo.getCurrentPage();
// 每页显示记录数
int pageSize = pageInfo.getPageSize();
// 记录偏移量
int offset = (currentPage - 1) * pageSize;
// 重写SQL, 加入分页逻辑
sql = sql.trim() + " LIMIT " + offset + "," + pageSize;
LOGGER.info("SQL Command Type【{}】, method【{}】 need paing.", sqlCmdType, methodName);
// 将重写完的分页SQL语句覆盖掉原有的SQL语句
metaObject.setValue("delegate.boundSql.sql", sql);
}
}
LOGGER.info("mybatis intercept sqlID: {}, sql: \n{}", methodName, sql);

// 打印 SQL 执行时间
long startTime = System.currentTimeMillis();
Object object = invocation.proceed();
LOGGER.info("{} execute time: {} ms.", methodName, System.currentTimeMillis() - startTime);

return object;
}

/**
* 获取代理对象
* */
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}

/**
* 设置代理对象的参数
*
* @param properties config(sql-map-config.xml)中配置的 plugin 对应的 property
* */
@Override
public void setProperties(Properties properties) {
// 缺省时, 默认mysql
dialect = properties.getProperty("dialect", "mysql");

pageSqlId = properties.getProperty("pageSqlId");
checkParam("pageSqlId", pageSqlId);

pageParam = properties.getProperty("pageParam");
checkParam("pageParam", pageParam);

System.out.println("mybatis intercept dialect: " + dialect + ", pageSqlId: " + pageSqlId + ", pageParam: " + pageParam);
}


private void checkParam(String key, String value) {
if (StringUtils.isEmpty(value)) {
try {
throw new PropertyException(key + " property is not found.");
} catch (PropertyException e) {
e.printStackTrace();
}
}
}
}

 

1.4. 分页对象实体类 PageInfo

public class PageInfo {
private int currentPage;
private int pageSize;

public PageInfo(int currentPage, int pageSize) {
this.currentPage = currentPage;
this.pageSize = pageSize;
}

public int getCurrentPage() {
return currentPage;
}

public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}

public int getPageSize() {
return pageSize;
}

public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}

 

1.5. mapper 文件 SQL 配置信息

<select id="findUsers" parameterType="Long" resultType="User">
select *
from smw_user
</select>

 

1.6. 实际项目中使用

@Controller
@RequestMapping("/user")
public class UserController {

@RequestMapping("findUsers")
@ResponseBody
public AIResponse findUsers() {
Map<String, Object> params = new HashMap<>();
PageInfo pageInfo = new PageInfo(1, 5);
// 引入 MyBatis 分页插件
params.put("pageInfo", pageInfo);
List<User> users = userService.findUsers(params);
logger.info("users size: " + users.size());
return AIResponse.success(users);
}

}

 

2. 使用 Github 开源分页插件


标签:插件,分页,pageSize,int,适配,mybatis,currentPage,public,自定义
From: https://blog.51cto.com/u_15891990/5908455

相关文章

  • Dockerfile自定义镜像、CentOS安装DockerCompose及Docker镜像仓库
    目录​​一、Dockerfile自定义镜像​​​​案例:基于java:8-alpine镜像,将一个Java项目构建为镜像​​​​二、CentOS安装DockerCompose​​​​案例:将cloud-demo微服务集群利......
  • jsonwebtoken自动生成token插件
    安装npmijsonwebtoken引入require("jsonwebtoken")配置解析......
  • IDEA使用 Alibaba Cloud Toolkit 插件 自动打包部署maven项目至服务器
    1.首先安装插件AlibabaCloudToolkit安装成后,会提示重启IDEA。我这里已经显示安装过插件了。2.打开插件工具Tool>>AlibabaCloud>>DeploytoHost配置远程服务器......
  • 爬虫之xpath插件下载与安装
    目录简介:下载xpath文件打开chrome浏览器点击右上角小圆点更多工具、阔展程序拖拽xpath插件放到阔展程序如果失效,再次拖拽关闭浏览器重新打开按ctrl+shift+x出现......
  • Form表单序列化Json插件-jquery.serializejson.min.js
    Form表单参数序列化成Json对象:​​1.使用serializeJsonObject​​​​2.jquery.serializejson.min.js​​1.使用serializeJsonObject在低版本的jQ中,可以使用serializeJso......
  • 适配动态 | 11月份SequoiaDB与8款产品完成互认证
    11月,巨杉数据库与超聚变、金仕达、方正国际、鸿数科技、爱数、轻流6家合作伙伴的8款产品完成互认证工作,上下游生态不断完善。数据库是数字经济建设的基础,良好的生态建设能......
  • Eclipse配置springIDE插件、搭建测试环境、简单的demo
    1.Spring框架简介(以下这以下这段话可用于面试求职):Spring为JavaEE开发提供了一个轻量级的解决方案,主要表现为:IOC(或者叫做DI)的核心机制,提供了bean工厂(Spring容器),降低了业务......
  • Sold Edge 插件 注册
    SolidEdgeAddInDemo NuGetThisprojectmakesuseoftheSolidEdge.CommunityopensourceprojectonGitHub.TheSolidEdge.Communityprojectispublishedvi......
  • 自定义的Qt时间轴控件
    这是一个垂直的时间轴,显示效果非常简单,但不能显示有格式的文本。如果想显示有格式文本可以把右侧显示本文的位置换成QLabel控件去显示有格式文本。如果想改变文本行间距,根......
  • 自定义hooks
    importReact,{useState,useEffect}from'react';exportconstuseStateHooks=(val:any)=>{  let[value,setValue]=useState(val);  constsetFunc=(v:any)=......