当前位置: 代码网 > it编程>编程语言>Java > MyBatis插件开发的完整详细例子(附注释和总结)

MyBatis插件开发的完整详细例子(附注释和总结)

2025年04月27日 Java 我要评论
mybatis 插件(interceptor)允许开发者在已映射语句执行过程中的某一点进行拦截调用,从而实现自定义逻辑。以下是一个完整的 mybatis 插件开发示例,涵盖所有使用场景,并附有详细注释

在这里插入图片描述

mybatis 插件(interceptor)允许开发者在已映射语句执行过程中的某一点进行拦截调用,从而实现自定义逻辑。以下是一个完整的 mybatis 插件开发示例,涵盖所有使用场景,并附有详细注释和总结。

1. mybatis 插件基础

mybatis 允许拦截以下接口的方法:

  • executorupdatequeryflushstatementscommitrollbackgettransactioncloseisclosed
  • parameterhandlergetparameterobjectsetparameters
  • resultsethandlerhandleresultsetshandlecursorresultsetshandleoutputparameters
  • statementhandlerprepareparameterizebatchupdatequery

2. 插件开发示例

2.1. 自定义插件类

创建一个自定义插件类 myplugin,该插件将拦截 executor 的 query 方法和 statementhandler 的 prepare 方法。

import org.apache.ibatis.executor.executor;
import org.apache.ibatis.mapping.boundsql;
import org.apache.ibatis.mapping.mappedstatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.resulthandler;
import org.apache.ibatis.session.rowbounds;
import org.apache.ibatis.statement.statementhandler;

import java.sql.connection;
import java.sql.statement;
import java.util.properties;

@intercepts({
    @signature(type = executor.class, method = "query", args = {mappedstatement.class, object.class, rowbounds.class, resulthandler.class}),
    @signature(type = statementhandler.class, method = "prepare", args = {connection.class, integer.class})
})
public class myplugin implements interceptor {

    @override
    public object intercept(invocation invocation) throws throwable {
        // 获取被拦截方法的参数
        object[] args = invocation.getargs();

        // 拦截 executor.query 方法
        if (invocation.gettarget() instanceof executor) {
            mappedstatement ms = (mappedstatement) args[0];
            object parameter = args[1];
            rowbounds rowbounds = (rowbounds) args[2];
            resulthandler resulthandler = (resulthandler) args[3];

            boundsql boundsql = ms.getboundsql(parameter);
            string sql = boundsql.getsql();
            system.out.println("executing sql: " + sql);

            // 执行原方法
            return invocation.proceed();
        }

        // 拦截 statementhandler.prepare 方法
        if (invocation.gettarget() instanceof statementhandler) {
            statementhandler statementhandler = (statementhandler) invocation.gettarget();
            connection connection = (connection) args[0];
            integer integer = (integer) args[1];

            // 获取原始 sql
            boundsql boundsql = statementhandler.getboundsql();
            string originalsql = boundsql.getsql();
            system.out.println("original sql: " + originalsql);

            // 修改 sql(例如添加注释)
            string newsql = "/* myplugin */ " + originalsql;
            boundsql newboundsql = new boundsql(
                boundsql.getmappedstatement().getconfiguration(),
                newsql,
                boundsql.getparametermappings(),
                boundsql.getparameterobject()
            );
            metaobject metaobject = systemmetaobject.forobject(statementhandler);
            metaobject.setvalue("delegate.boundsql", newboundsql);

            // 执行原方法
            return invocation.proceed();
        }

        return invocation.proceed();
    }

    @override
    public object plugin(object target) {
        // 使用 plugin.wrap 包装目标对象
        return plugin.wrap(target, this);
    }

    @override
    public void setproperties(properties properties) {
        // 设置插件属性(可选)
    }
}

2.2. 配置插件

在 mybatis-config.xml 中配置自定义插件:

<?xml version="1.0" encoding="utf-8" ?>
<!doctype configuration public "-//mybatis.org//dtd config 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置插件 -->
    <plugins>
        <plugin interceptor="com.example.plugin.myplugin">
            <!-- 可以设置插件属性 -->
            <!-- <property name="propertyname" value="propertyvalue"/> -->
        </plugin>
    </plugins>

    <!-- 其他配置... -->
</configuration>

2.3. 测试插件

编写测试代码来验证插件的功能:

import org.apache.ibatis.io.resources;
import org.apache.ibatis.session.sqlsession;
import org.apache.ibatis.session.sqlsessionfactory;
import org.apache.ibatis.session.sqlsessionfactorybuilder;

import java.io.reader;

public class plugintest {
    public static void main(string[] args) throws exception {
        // 读取 mybatis 配置文件
        reader reader = resources.getresourceasreader("mybatis-config.xml");
        sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(reader);

        try (sqlsession session = sqlsessionfactory.opensession()) {
            usermapper mapper = session.getmapper(usermapper.class);

            // 执行查询操作,触发插件拦截
            user user = mapper.selectuserbyid(1l);
            system.out.println("user: " + user.getname());
        }
    }
}

3. 核心使用场景

3.1. 日志记录

在 executor 的 query 和 update 方法中添加日志记录,便于调试和监控。

3.2. sql 修改

在 statementhandler 的 prepare 方法中修改 sql 语句,例如添加统一的注释或进行性能优化。

3.3. 参数处理

在 parameterhandler 的 setparameters 方法中对参数进行预处理,如加密、格式化等。

3.4. 结果集处理

在 resultsethandler 的 handleresultsets 方法中对结果集进行后处理,如数据脱敏、缓存等。

4. 表格整理总结

场景拦截接口及方法具体应用示例代码片段
日志记录executor.queryexecutor.update在执行 sql 前后记录日志system.out.println("executing sql: " + sql);
sql 修改statementhandler.prepare修改或优化 sql 语句string newsql = "/* myplugin */ " + originalsql;
参数处理parameterhandler.setparameters对参数进行预处理(如加密)preparedstatement.setstring(1, encrypt(parameter));
结果集处理resultsethandler.handleresultsets对查询结果进行后处理(如脱敏)resultlist.foreach(item -> item.setemail(maskemail(item.getemail())));
性能监控executor.queryexecutor.update记录 sql 执行时间long starttime = system.currenttimemillis(); ... long endtime = ...
分页支持statementhandler.parameterize动态添加分页参数preparedstatement.setint(1, offset); preparedstatement.setint(2, limit);

5. 最佳实践建议

  • 理解底层行为:在重写方法时,需理解其底层行为,避免破坏 mybatis 的核心功能。
  • 谨慎修改 sql:修改 sql 时要确保语法正确,避免引入潜在的 sql 注入风险。
  • 合理使用属性:通过 setproperties 方法为插件设置属性,增强灵活性。
  • 单元测试:编写单元测试验证插件功能,确保其在各种场景下的稳定性。
  • 文档记录:详细记录插件的使用方法和注意事项,便于团队成员理解和维护。

通过以上示例和总结,可以全面掌握 mybatis 插件的开发和应用场景。

到此这篇关于mybatis插件开发的完整详细例子的文章就介绍到这了,更多相关mybatis插件开发内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com