首页 > 数据库 >MybatisPlus拦截器打印完整SQL、分页、自动填充处理

MybatisPlus拦截器打印完整SQL、分页、自动填充处理

时间:2022-08-31 15:36:15浏览次数:73  
标签:拦截器 MybatisPlus Object class metaObject sql SQL new public

MybatisPlus拦截器打印完整SQL

MybatisPlus 虽然也自带了一个打印 SQL 的配置,但是不方便查看,也没有时间统计

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

拦截器PrintSqlInterceptor

/**
 * @author CoderKK
 * @date 2020-09-01 00:13
 */
@Slf4j
@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 PrintSqlInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object parameter = null;
        if (invocation.getArgs().length > 1) {
            parameter = invocation.getArgs()[1];
        }
        String sqlId = mappedStatement.getId();
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        Configuration configuration = mappedStatement.getConfiguration();
        long start = System.currentTimeMillis();
        Object returnValue = invocation.proceed();
        long time = System.currentTimeMillis() - start;
        showSql(configuration, boundSql, time, sqlId);
        return returnValue;
    }

    private static void showSql(Configuration configuration, BoundSql boundSql, long time, String sqlId) {
        Object parameterObject = boundSql.getParameterObject();
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        //替换空格、换行、tab缩进等
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
        if (parameterMappings.size() > 0 && parameterObject != null) {
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    if (metaObject.hasGetter(propertyName)) {
                        Object obj = metaObject.getValue(propertyName);
                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        Object obj = boundSql.getAdditionalParameter(propertyName);
                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
                    }
                }
            }
        }
        logs(time, sql, sqlId);
    }

    private static String getParameterValue(Object obj) {
        String value;
        if (obj instanceof String) {
            value = "'" + obj + "'";
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            value = "'" + formatter.format(new Date()) + "'";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "";
            }
        }
        return value.replace("$", "\\$");
    }

    private static void logs(long time, String sql, String sqlId) {
        StringBuilder sb = new StringBuilder()
                .append(" Time:").append(time)
                .append(" ms - ID:").append(sqlId)
                .append(StringPool.NEWLINE).append("Execute SQL:")
                .append(sql).append(StringPool.NEWLINE);
        log.info(sb.toString());
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties0) {
    }
}

MybatisPlus配置 MybatisPlusConfig

package com.example.demojs.config;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.example.demojs.common.PrintSqlInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


@Configuration
public class MybatisPlusConfig {

    /**
     * mybatis-plus分页插件
     */

/*
    // 旧版
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

    // 新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    // 如何区分新旧版呢?其实你把这两种代码都复制到你的项目里,哪个类存在就用哪个方法。
    // 3.4.0版本对此部分有更新,如果是旧版本升级,会出现分页失效问题,同时idea会提示PaginationInterceptor过时,新版本改用了MybatisPlusInterceptor

*/

    /**
     *自定义mybatis插件 注入方式一
     */
/*
    @Bean
    public MybatisPlusInterceptor mybatisInterceptor() {
        MybatisPlusInterceptor mybatisInterceptor = new MybatisPlusInterceptor();
        Properties properties = new Properties();
        properties.setProperty("name", name);
        mybatisInterceptor.setProperties(properties);
        return mybatisInterceptor;
    }
*/
    /**
     *自定义mybatis插件 注入方式二
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> {
            //插件拦截链采用了责任链模式,执行顺序和加入连接链的顺序有关
            //MybatisInterceptor mybatisInterceptor = new MybatisInterceptor();
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            //设置参数,比如阈值等,可以在配置文件中配置
            Properties properties = new Properties();
            //properties.setProperty("name", name);
            mybatisPlusInterceptor.setProperties(properties);

                //自定义打印SQL
                PrintSqlInterceptor printSqlInterceptor = new PrintSqlInterceptor();
                configuration.addInterceptor(printSqlInterceptor);

        };
    }


    /**
     * mybatis-plus SQL执行效率插件【生产环境可以关闭】 3.3.2版本移除了该功能,3.0.3和3.0.3之前版本支持。
     */
  /*
    @Bean
    public PerformanceInterceptor performanceInterceptor() {
        return new PerformanceInterceptor();
    }
    */

}

打印效果

2022-08-29 16:42:03.782  INFO 17476 --- [nio-8080-exec-2] c.e.demojs.common.PrintSqlInterceptor    :  Time:397 ms - ID:com.example.demojs.dao.UserMapper.insert
Execute SQL:INSERT INTO test_user ( id, user_id, phone, birthday, sex ) VALUES ( 1564171509361389569, 'abc', '13988776664', 2022-08-29T16:41:59.514, 1 )

自动填充插件

/**
 * @author CoderKK
 * @date 2020/9/6 15:21
 * @desc 自动填充处理器类
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 插入时的填充策略
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }

    /**
     * 更新时的填充策略
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
}

实体类记得加注解

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
    private LocalDateTime createTime;

    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
    private LocalDateTime updateTime;

分页插件

注入分页插件后,如何使用呢?

mapper写法:

// 这是mapper自己提供的方法,参数是wrapper 适用于单表查
 <P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);

// 自定义sql,适用于多表联查
IPage<UserVO> queryUserList(Page<UserVO> page,  @Param("dto") ConditionDTO conditionDTO);

标签:拦截器,MybatisPlus,Object,class,metaObject,sql,SQL,new,public
From: https://www.cnblogs.com/geek233/p/16643272.html

相关文章

  • Dapper.LiteSql 一款基于Dapper的ORM
    写了这么久,代码没有越写越多,代码量的数量级没变,用SourceCounter代码统计工具统计了一下,一共4000多行代码。ADO.NET换成Dapper后,我迷茫了,因为LiteSql做的工作变少了,它存在......
  • 转:postgresql-创建主键自增的表
    之前一直用的mysql,这个也基本上是主流,主键自增是很多建表规范中的硬性要求,不过这两种数据库主键自增的区别还是很大的通常navicat中对mysql主键自增直接客户端指定即......
  • Postgresql 解决pg掉电后无法重启的问题
    1、机房断电后重启pg数据库,报如下错误:Aug3110:55:53localhost.localdomainpostmaster[1716]:2022-08-3110:55:53.775CST[1716]LOG:couldnotopendirectory"p......
  • postgresql 错误:关系“global/1213”中的块0存在无效项
    问题Postgresql12连接时提示错误:关系“global/1213”中的块0存在无效项解决方案提示:此操作将销毁数据,即损坏页面上的所有行!但是,它允许您跳过错误,并从表中......
  • springBoot中新建拦截器
    最近项目中需要将请求中的header中增加几个字段,第一反应就是可不可以用拦截器拦截请求后将字段放进请求头中,经过网上一番学习后发现该方案可行,故将此方法记录下来供大家参......
  • Mysql定时备份指南
    Mysql定时备份指南1、登录数据库服务器,创建目录mkdir-p/data/mysqlbak/datamkdir-p/data/mysqlbak/scriptsmkdir-p/data/mysqlbak/logs2、创建备份脚本文件Vi......
  • mysql安装及10061错误解决
    mysql出现10061错误解决方法 1.开始菜单->运行(cmd)->寻径到MySQL文件中的bin目录下如:D:\MySQL\mysql-5.6.24-win32\bin2.输入指令:mysqld--skip-grant-tables 回车//......
  • mysql用户重命名
    如何修改mysql默认账户名root?首先说一下为什么我要改这个root用户名,正常来说,数据库用户名又不经常更改,用啥都是应用,为什么非要改呢?因为最近在搞一个项目,本地数据库用户名为......
  • Mysql定时备份指南
    Mysql定时备份指南1、登录数据库服务器,创建目录mkdir-p/data/mysqlbak/datamkdir-p/data/mysqlbak/scriptsmkdir-p/data/mysqlbak/logs2、创建备份脚本文件Vi......
  • 【MySQL】MariaDB使用connect存储引擎访问SQLServer中的表
    借助connect存储引擎,Mariadb可以访问任何ODBC数据源。本文是以CentOS7为例。安装的内容有:ODBCdriver,unixODBC 1.下载ODBC对应linux的驱动下载地址:https://docs.mi......