目录
- 1. MyBATis 插件基础
- 2. 插件开发示例
- 2.1. 自定义插件类
- 2.2. 配置插件
- 2.3. 测试插件
- 3. 核心使用场景
- 3.1. 日志记录
- 3.2. SQL 修改
- 3.3. 参数处理
- 3.4. 结果集处理
- 4. 表格整理总结
- 5. 最佳实践建议
MyBatis 插件(Interceptor)允许开发者在已映射语句执行过程中的某一点进行拦截调用,从而实现自定义逻辑。以下是一个完整的 MyBatis 插件开发示例,涵盖所有使用场景,并附有详细注释和总结。
1. MyBatis 插件基础
MyBatis 允许拦截以下接口的方法:
- Executor:
update
,query
,flushStatements
,commit
,rollback
,getTransaction
,close
,isClosed
- ParameterHandler:
getParameterObject
,setParameters
- ResultSetHandler:
handleResultSets
,handleCursorResultSets
,handleOutputParameters
- StatementHandler:
prepare
,parameterize
,batch
,update
,query
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.ut编程客栈il.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> <!-- 配置插件 --> <pphplugins> <FSUledw;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.pythongetMapper(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.query , Executor.update | 在执行 SQL 前后记录日志 | System.out.println("Executing SQL: " + sql); |
SQL 修改 | StatementHandler.prepare | 修改或优化 SQLhttp://www.devze.com 语句 | 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插件开发内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论