美文网首页
mybatis 打印sql日志

mybatis 打印sql日志

作者: 程序员老帮菜 | 来源:发表于2020-07-27 14:18 被阅读0次

查看mybatis源码,mybatis内部封装了日志接口,可以对接当前留下的所有的日志实现
在实际开发过程中或者生产环境查找定位问题,需要查看执行的sql语句,以下详细说明下如何将sql日志打印出来

我们借助问题的方式进行分析

为什么我的项目中直接将根目录(root)日志级别调整为DEBUG,就可以输出sql日志,调高级别就打印不出来了呢

直接贴源码


为什么项目是DEBUG级别,但是还是不能输出sql日志呢

先贴源码


看源码可以看出,mybatis是按照顺序 slf4j->commonsLog->log4j2->log4j->jdkLog->noLog(空实现),这个顺序尝试加载日志实现的,
可能本地有多中日志实现,而项目中的日志实现与mybatis加载的日志实现不同导致的,排除无用的日志实现既可,或者高版本mybatis(高于3.2.0的版本)可以直接设置mybatis的日志实现

不想调整root的日志级别,可以只打印mybatis的日志吗

调整root节点的日志级别,会打印出其他jar包的日志,影响我们查看问题
可以直接跳转mybatis日志级别实现打印sql日志的需求

调整mybatis日志级别及日志实现

高版本(版本高于3.2.0)mybatis设置日志实现

MyBatis 配置文件

<settings>
    <setting name="logPrefix" value="dao."/> <!-- 设置前缀为dao -->
    <setting name="logImpl" value="log4j"/> <!-- 设置使用log4j为日志实现类 -->
</settings>

MyBatis api写法

Configuration configuration = new Configuration();
//<!-- 设置前缀为dao 用于单独设置指定mapper的日志基本-->
configuration.setLogPrefix("dao.");
// 实现了Log接口的实现类即可
configuration.setLogImpl(Log4j2Impl.class);

低版本(版本低于3.2.0)mybatis设置日志级别

<Appenders>
     // stdout 打印在控制台,可以知道输出到文件
        <Console name="stdout" target="SYSTEM_OUT">
            <PatternLayout pattern="${var.output.pattern}" />
        </Console>
</Appenders>

<Loggers>
     //根目录设置为info,避免其他jar包日志输出
        <AsyncRoot level="info" includeLocation="true">
            <AppenderRef ref="stdout" />
        </AsyncRoot>
        <!--3.2以下-->
        <AsyncLogger name="java.sql.Connection" level="DEBUG" includeLocation="true" additivity="false">
            <AppenderRef ref="stdout" />
        </AsyncLogger>
        <AsyncLogger name="java.sql.PreparedStatement" level="DEBUG" includeLocation="true" additivity="false">
            <AppenderRef ref="stdout" />
        </AsyncLogger>
        <AsyncLogger name="java.sql.ResultSet" level="DEBUG" includeLocation="true" additivity="false">
            <AppenderRef ref="stdout" />
        </AsyncLogger>
</Loggers>

由于mybatis日志打印是使用jdk代理实现的,如果日志级为DEBUG,会走代理类打印日志,其他级别会走原无日志逻辑,且java.sql.Connection是开启代理日志的入口,所有java.sql.Connection必须设置为DEBUG级别

  • 源码-org.apache.ibatis.executor.BaseExecutor#getConnection:
protected Connection getConnection(Log statementLog) throws SQLException {
        Connection connection = this.transaction.getConnection();
 //ConnectionLogger为日志的代理类
        return statementLog.isDebugEnabled() ? 
ConnectionLogger.newInstance(connection, statementLog, this.queryStack) : connection;
    }

  • 有兴趣可以查看相关日志代理类ConnectionLogger/PreparedStatementLogger/ResultSetLogger

高版本(版本高于3.2.0)mybatis设置日志级别

高版本指定mapper中的方法打印日志

由于Log4j中的log的继承关系,配置mapper的上层包路径的日志级别也可以打印日志,比如com.example.log.mapper或com.example.log.mapper.UserMapper

  • 未配置logPrefix的demo
<AsyncLogger name="com.example.log.mapper.UserMapper.getAllUsers" level="DEBUG" includeLocation="true" additivity="false">
    <AppenderRef ref="stdout"/>
</AsyncLogger>

  • 配置logPrefix的demo,logPrefix=dao
<AsyncLogger name="dao.com.example.log.mapper.UserMapper.getAllUsers" level="DEBUG" includeLocation="true" additivity="false">
    <AppenderRef ref="stdout"/>
</AsyncLogger>

总结

mybatis低版本日志打印存在缺点: 当开启打印SQL日志后,会打印所有正在执行的SQL语句,不能实现针对特定SQL的打印,基于此 MyBatis 从3.2.0版本之后重新实现了相关功能

相关文章

网友评论

      本文标题:mybatis 打印sql日志

      本文链接:https://www.haomeiwen.com/subject/hbrzlktx.html