在開發過程中, 經常會遇到想要看到應用所執行的 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