MyBatis 中的插件可以实现哪些功能

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: MyBatis 中的插件可以实现哪些功能

MyBatis 中的插件可以实现哪些功能


概述


MyBatis 是一个流行的 Java 持久层框架,它提供了一种简单而强大的方式来访问关系型数据库。MyBatis 的核心在于 SQL 映射,它将数据库表和 Java 对象之间的映射关系定义在 XML 或注解中。MyBatis 还提供了插件机制,允许开发者在 SQL 执行过程中对其进行拦截和修改。本文将介绍 MyBatis 插件的基本原理和常见用法。


image.png


插件机制的基本原理


MyBatis 插件机制是基于 Java 动态代理机制实现的。它允许开发者在 SQL 执行过程中对其进行拦截和修改,从而实现一些自定义功能。插件机制的核心在于 Interceptor 接口和 Plugin 类,其中 Interceptor 接口定义了插件的具体实现,而 Plugin 类则用于生成代理对象。


Interceptor 接口


Interceptor 接口定义了 MyBatis 插件的具体实现。它有三个方法:


  1. intercept(Invocation invocation):该方法用于拦截 SQL 执行过程。Invocation 对象包含了执行 SQL 所需的信息,开发者可以在该方法中对 SQL 进行修改或增强。
  2. plugin(Object target):该方法用于生成代理对象。开发者需要返回一个代理对象,该对象会自动拦截 SQL 执行过程。
  3. setProperties(Properties properties):该方法用于设置插件的属性。开发者可以在该方法中读取和设置插件的配置信息。


Plugin 类


Plugin 类用于生成代理对象。它有两个静态方法:


  1. wrap(Object target, Interceptor interceptor):该方法用于生成代理对象。target 参数表示被代理的对象,interceptor 参数表示插件的具体实现。
  2. wrap(Object target, Interceptor interceptor, String[] interceptorNames):该方法用于生成代理对象。target 参数表示被代理的对象,interceptor 参数表示插件的具体实现,interceptorNames 参数表示其他插件的名称,用于确定插件的执行顺序。


常见插件的用法


分页插件


分页是 Web 应用程序中常用的功能之一,它可以帮助用户浏览大量数据。MyBatis 提供了分页支持,但是需要在 SQL 中手动编写分页逻辑。为了简化分页操作,可以使用 MyBatis 分页插件。该插件会自动拦截 SQL 执行过程,并在 SQL 中添加分页逻辑。


插件实现


下面是一个简单的分页插件实现:


@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class PaginationInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        Object parameterObject = boundSql.getParameterObject();
        if (parameterObject instanceof PageRequest) {
            PageRequest pageRequest = (PageRequest) parameterObject;
            String sql = boundSql.getSql();
            int count = getCount(statementHandler, boundSql);
            pageRequest.setTotal(count);
            String pageSql = getPageSql(sql, pageRequest);
            ReflectUtil.setFieldValue(boundSql, "sql", pageSql);
        }
        return invocation.proceed();
    }
    private int getCount(StatementHandler statementHandler, BoundSql boundSql) throws SQLException {
        Connection connection = statementHandler.getConnection();
        String countSql = "SELECT COUNT(*) FROM (" + boundSql.getSql() + ") tmp";
        PreparedStatement countStatement = connection.prepareStatement(countSql);
        BoundSql countBoundSql = new BoundSql(statementHandler.getConfiguration(), countSql, boundSql.getParameterMappings(), boundSql.getParameterObject());
        setParameters(count### 日志插件
MyBatis 内置了日志功能,可以输出 SQL 执行过程中的日志信息。但是,如果需要自定义日志输出格式或将日志输出到不同的目标,可以使用 MyBatis 日志插件。
#### 插件实现
下面是一个简单的日志插件实现:
```java
@Intercepts({
    @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
    @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class LoggingInterceptor implements Interceptor {
    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        String statementId = mappedStatement.getId();
        Object parameterObject = invocation.getArgs()[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
        long start = System.currentTimeMillis();
        Object result = invocation.proceed();
        long end = System.currentTimeMillis();
        long time = end - start;
        if (time > 1) {
            String message = String.format("[MyBatis] %s: %s (%dms)", statementId, sql, time);
            logger.info(message);
        }
        return result;
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}

该插件会拦截所有的 SQL 执行操作,并输出执行日志。在 SQL 执行时间超过 1 毫秒时,会将执行时间记录在日志中。


签名插件


MyBatis 中的 SQL 语句可以使用动态 SQL 和参数映射等功能,使得 SQL 语句更加灵活。但是,这也带来了一些安全风险,因为恶意用户可能会通过参数注入攻击来执行非法 SQL 语句。为了解决这个问题,可以使用 MyBatis 签名插件。该插件会对 SQL 语句进行签名,防止参数注入攻击。


插件实现


下面是一个简单的签名插件实现:


@Intercepts({
    @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
})
public class SignatureInterceptor implements Interceptor {
    private static final String SIGNATURE = "MyBatis";
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
        PreparedStatement preparedStatement = (PreparedStatement) invocation.getArgs()[0];
        Object parameterObject = parameterHandler.getParameterObject();
        if (parameterObject != null) {
            Class<?> parameterClass = parameterObject.getClass();
            Field[] fields = parameterClass.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(SignatureField.class)) {
                    String fieldName = field.getName();
                    Object fieldValue = ReflectUtil.getFieldValue(parameterObject, fieldName);
                    if (fieldValue != null && fieldValue instanceof String) {
                        String value = (String) fieldValue;
                        if (value.indexOf(SIGNATURE) == -1) {
                            value = value + SIGNATURE;
                            ReflectUtil.setFieldValue(parameterObject, fieldName, value);
                        }
                    }
                }
            }
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}

该插件会对所有参数中被 @SignatureField 注解的字段进行签名。签名内容为固定值 “MyBatis”,可以根据实际情况进行修改。在 SQL 执行过程中,如果参数中的字段值不包含该签名,插件会自动添加签名。这样可以防止参数注入攻击。


插件的配置


在使用 MyBatis 插件时,需要对其进行配置。可以使用 XML 或注解进行配置。


XML 配置


在 MyBatis 的 XML 配置文件中,可以使用 <plugins> 元素来配置插件。例如


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
SQL XML Java
8、Mybatis-Plus 分页插件、自定义分页
这篇文章介绍了Mybatis-Plus的分页功能,包括如何配置分页插件、使用Mybatis-Plus提供的Page对象进行分页查询,以及如何在XML中自定义分页SQL。文章通过具体的代码示例和测试结果,展示了分页插件的使用和自定义分页的方法。
8、Mybatis-Plus 分页插件、自定义分页
|
20天前
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
114 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
10天前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
20天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
Java 数据库连接 容器
Mybatis-Plus核心功能
Mybatis-Plus核心功能
|
2月前
|
SQL Java 数据库连接
解决mybatis-plus 拦截器不生效--分页插件不生效
本文介绍了在使用 Mybatis-Plus 进行分页查询时遇到的问题及解决方法。依赖包包括 `mybatis-plus-boot-starter`、`mybatis-plus-extension` 等,并给出了正确的分页配置和代码示例。当分页功能失效时,需将 Mybatis-Plus 版本改为 3.5.5 并正确配置拦截器。
706 6
解决mybatis-plus 拦截器不生效--分页插件不生效
|
2月前
|
SQL 存储 Java
原生JDBC简单实现Mybatis核心功能
本文介绍了在Vertx项目中使用Tdengine时,因缺乏异步JDBC驱动而采用同步驱动结合`vertx.executeBlocking`实现异步查询的方法。文中详细描述了自行开发的一个简易JDBC工具,该工具实现了SQL参数绑定与返回值映射至实体类的功能,简化了原生JDBC的繁琐操作。通过具体示例展示了其实现过程及代码细节,并与原生JDBC进行了对比,突显了其便捷性和实用性。
|
2月前
|
SQL XML Java
springboot整合mybatis-plus及mybatis-plus分页插件的使用
这篇文章介绍了如何在Spring Boot项目中整合MyBatis-Plus及其分页插件,包括依赖引入、配置文件编写、SQL表创建、Mapper层、Service层、Controller层的创建,以及分页插件的使用和数据展示HTML页面的编写。
springboot整合mybatis-plus及mybatis-plus分页插件的使用
|
3月前
|
供应链 前端开发 Java
服装库存管理系统 Mybatis+Layui+MVC+JSP【完整功能介绍+实现详情+源码】
该博客文章介绍了一个使用Mybatis、Layui、MVC和JSP技术栈开发的服装库存管理系统,包括注册登录、权限管理、用户和货号管理、库存管理等功能,并提供了源码下载链接。
服装库存管理系统 Mybatis+Layui+MVC+JSP【完整功能介绍+实现详情+源码】
|
3月前
|
Java 数据库 Spring
MyBatisPlus分页插件在SpringBoot中的使用
这篇文章介绍了如何在Spring Boot项目中配置和使用MyBatis-Plus的分页插件,包括创建配置类以注册分页拦截器,编写测试类来演示如何进行分页查询,并展示了测试结果和数据库表结构。
MyBatisPlus分页插件在SpringBoot中的使用
下一篇
无影云桌面