在开发过程中, 经常会遇到想要看到应用所执行的 sql 这样的需求.
比如你写了一个查询的功能, 但查询出来的结果与你预期的不符合, 你想搞清楚到底哪里出了问题, 你自然需要看看所执行的 sql 语句, 必要的话甚至还要亲自拷贝到数据库里去查查.
自然, 这就要求应用要能把执行的 sql 输出出来. 以常用的 mybatis 框架为例, 来看一个最终的效果:
14:48 ==> Preparing: select * from user where id = ?
14:48 ==> Parameters: 1(Integer)
14:48 <== Total: 1
另注: 这里的日志布局我启用了一种极简的风格, 只有"分钟:秒数", 具体见 配置简化开发阶段日志输出布局 的介绍.
那么, 在 mybatis 里, 这个要怎么做到呢?
配置 sql 输出
具体来说, 是要增加一个日志级别的配置, 将 dao(或 mapper) 包级别调整到 DEBUG
.
示例:
# log sql statement
logging.level.net.xiaogd.sample.mybatis.dao=DEBUG
注: 上述配置建议放在你的本地开发环境配置文件中, 通常为 application-dev.properties, 关于 spring-boot 的 分环境配置 的
profile
机制, 如不熟悉请自行查阅网络了解.
对应工程代码包结构如下:
注: 我的代码结构下, mybatis 相关的类放到了 dao 这个包下, 你的如果不是这样, 可以根据自己的情况加以调整.
在上述配置下, 执行以下测试:
package net.xiaogd.sample.mybatis.dao.user;
import lombok.extern.slf4j.Slf4j;
import net.xiaogd.sample.mybatis.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@Slf4j
@RunWith(SpringRunner.class)
@MybatisTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class SimpleTest {
@Autowired
private UserDao userDao;
@Test
public void testGetUserById() {
User user = userDao.findUserById(1);
log.info("user find id: {}", user.getId());
}
}
相应的 dao 接口:
package net.xiaogd.sample.mybatis.dao.user;
import net.xiaogd.sample.mybatis.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserDao {
@Select("select * from user where id = #{id}")
User findUserById(int id);
}
相应的 sql 语句, 参数值及查询的总数都会打印出来:
14:48 ==> Preparing: select * from user where id = ?
14:48 ==> Parameters: 1(Integer)
14:48 <== Total: 1
输出结果集
如果想进一步输出结果集, 则可以进一步把日志级别提升到 TRACE
. 如下:
# log sql statement and result set
logging.level.net.xiaogd.sample.mybatis.dao=TRACE
警告: 可能导致大量的日志输出, 非必要情况下不要启用, 且仅可以在本地开发环境调试情况下启用!
对于下述的数据表:
最终的输出如下:
17:36 ==> Preparing: select * from user
17:36 ==> Parameters:
17:36 <== Columns: id, username, password, nick_name
17:36 <== Row: 1, admin, 123456, 管理员
17:36 <== Row: 2, root, root, 根用户
17:36 <== Total: 2
可以看到字段及每行的值都被打印出来了.
遗留问题
当然了, 上述在输出 sql 语句时还有一个问题, 就是在有参数的情况下, 这个还不是最终的 sql, 而是类似于 jdbc 中的那种 prepare statement:
select * from user where id = ?
可以看到参数的值是用一个问号占位符代替的, 真正的参数值输出到了另一行.
如果要真的拷贝到数据库查看工具里执行, 比如 navicat 或者 mysql workbench 抑或是最简单的 mysql console 中, 我们还是得自行替换及拼凑最终的 sql.
虽然多数情况下这也不是特别麻烦, 但在特别多参数的情况下, 如果你发现执行结果不对, 用眼睛看输出的参数值似乎也没有问题, 自行去拼凑就有点麻烦了, 能否直接输出最终的 sql 呢? 也是有方式的, 我们将在下一篇再介绍这种方式.
参考文档
更多打印 sql 日志相关的配置, 请参考其官网: https://mybatis.org/mybatis-3/logging.html