查看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 配置文件

MyBatis api写法

Configuration configuration = new Configuration();
//
configuration.setLogPrefix("dao.");
// 实现了Log接口的实现类即可
configuration.setLogImpl(Log4j2Impl.class);
低版本(版本低于3.2.0)mybatis设置日志级别
// stdout 打印在控制台,可以知道输出到文件
//根目录设置为info,避免其他jar包日志输出

由于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

配置logPrefix的demo,logPrefix=dao

总结

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