查看mybatis源码,mybatis内部封装了日志接口,可以对接当前留下的所有的日志实现
在实际开发过程中或者生产环境查找定位问题,需要查看执行的sql语句,以下详细说明下如何将sql日志打印出来
我们借助问题的方式进行分析
为什么我的项目中直接将根目录(root)日志级别调整为DEBUG,就可以输出sql日志,调高级别就打印不出来了呢
直接贴源码
![](https://img.haomeiwen.com/i22519207/489ab70e42109907.png)
为什么项目是DEBUG级别,但是还是不能输出sql日志呢
先贴源码
![](https://img.haomeiwen.com/i22519207/3c7f75f96f69b508.png)
![](https://img.haomeiwen.com/i22519207/40554c3a04d3f9aa.png)
看源码可以看出,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版本之后重新实现了相关功能
网友评论