首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

MyBatis中如何实现自定义插件

  • 25-04-17 08:00
  • 3544
  • 7888
juejin.cn

比如可以使用自定义插件来添加分页参数,或统计sql的执行时间,实现方式为:

  1. 创建插件类并实现Interceptor接口
  • intercept():编写拦截逻辑,在目标方法前后执行自定义操作。
  • plugin():返回目标对象的代理对象。
  • setProperties():接收配置文件中的参数(可选)。
java
代码解读
复制代码
import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import java.sql.Connection; import java.util.Properties; @Intercepts({ @Signature( type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class} ) }) public class PaginationPlugin implements Interceptor { private String dialect = "mysql"; // 默认数据库类型 @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler handler = (StatementHandler) invocation.getTarget(); MetaObject metaObject = SystemMetaObject.forObject(handler); // 获取原始SQL和分页参数 BoundSql boundSql = handler.getBoundSql(); String originalSql = boundSql.getSql(); Object parameterObject = boundSql.getParameterObject(); // 检查是否包含分页参数 if (parameterObject instanceof Page) { Page page = (Page) parameterObject; // 修改SQL添加分页 String paginatedSql = buildPaginationSql(originalSql, page); metaObject.setValue("delegate.boundSql.sql", paginatedSql); // 设置分页参数(LIMIT和OFFSET) metaObject.setValue("delegate.boundSql.parameterObject", page.getData()); } return invocation.proceed(); } // 构建分页SQL private String buildPaginationSql(String sql, Page page) { int offset = (page.getPageNum() - 1) * page.getPageSize(); if ("mysql".equals(dialect)) { return sql + " LIMIT " + page.getPageSize() + " OFFSET " + offset; } else if ("oracle".equals(dialect)) { // Oracle分页逻辑(使用ROWNUM) return "SELECT * FROM ( SELECT tmp.*, ROWNUM rn FROM (" + sql + ") tmp ) WHERE rn > " + offset + " AND rn <= " + (offset + page.getPageSize()); } return sql; } @Override public Object plugin(Object target) { // 包装目标对象,返回代理 return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 提取参数 this.dialect = properties.getProperty("dialect", "mysql"); } }
  1. 使用@Intercepts注解指定拦截目标

@Signature注解定义要拦截的类、方法及参数类型。例如:

  • type:拦截的接口(如Executor、StatementHandler)。
  • method:方法名。
  • args:方法的参数类型数组。
  1. 注册插件到MyBatis配置
xml
代码解读
复制代码
<plugins> <plugin interceptor="com.example.PaginationPlugin"> <property name="dialect" value="mysql"/> plugin> plugins>
  1. mapper层使用示例
less
代码解读
复制代码
public interface UserMapper { @Pageable List selectByCondition(@Param("page") Page page, @Param("name") String name); }

注意事项:

  • 仅支持拦截四大接口:Executor、StatementHandler、ParameterHandler、ResultSetHandler。
  • 方法签名匹配:需确保@Signature中的参数类型与目标方法完全一致。
  • 性能影响:过度使用插件可能影响性能,建议仅在必要时使用。
注:本文转载自juejin.cn的Yharim的文章"https://juejin.cn/post/7491240940125995060"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

142
代码人生
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top