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

2025-05-14 05:56:34 102
魁首哥

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

1. mybatis 插件基础

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

  • executorupdate,query,flushstatements,commit,rollback,gettransaction,close,isclosed
  • parameterhandlergetparameterobject,setparameters
  • resultsethandlerhandleresultsets,handlecursorresultsets,handleoutputparameters
  • statementhandlerprepare,parameterize,batch,update,query

2. 插件开发示例

2.1. 自定义插件类

创建一个自定义插件类myplugin,该插件将拦截executorquery方法和statementhandlerprepare方法。

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中配置自定义插件:




    
    
        
            
            
        
    

    

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. 日志记录

executorqueryupdate方法中添加日志记录,便于调试和监控。

3.2. sql 修改

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

3.3. 参数处理

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

3.4. 结果集处理

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

4. 表格整理总结

场景拦截接口及方法具体应用示例代码片段
日志记录executor.query,executor.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.query,executor.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插件开发内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

分享
海报
102
上一篇:Java优化模糊搜索体验的方法详解 下一篇:SpringBoot UserAgentUtils获取用户浏览器的用法

忘记密码?

图形验证码