在開(kāi)發(fā)過(guò)程中, 經(jīng)常會(huì)遇到想要看到應(yīng)用所執(zhí)行的 sql 這樣的需求.
比如你寫(xiě)了一個(gè)查詢(xún)的功能, 但查詢(xún)出來(lái)的結(jié)果與你預(yù)期的不符合, 你想搞清楚到底哪里出了問(wèn)題, 你自然需要看看所執(zhí)行的 sql 語(yǔ)句, 必要的話(huà)甚至還要親自拷貝到數(shù)據(jù)庫(kù)里去查查.
自然, 這就要求應(yīng)用要能把執(zhí)行的 sql 輸出出來(lái). 以常用的 mybatis 框架為例, 來(lái)看一個(gè)最終的效果:
14:48 ==> Preparing: select * from user where id = ?
14:48 ==> Parameters: 1(Integer)
14:48 <== Total: 1
另注: 這里的日志布局我啟用了一種極簡(jiǎn)的風(fēng)格, 只有"分鐘:秒數(shù)", 具體見(jiàn) 配置簡(jiǎn)化開(kāi)發(fā)階段日志輸出布局 的介紹.
那么, 在 mybatis 里, 這個(gè)要怎么做到呢?
配置 sql 輸出
具體來(lái)說(shuō), 是要增加一個(gè)日志級(jí)別的配置, 將 dao(或 mapper) 包級(jí)別調(diào)整到 DEBUG
.
示例:
# log sql statement
logging.level.net.xiaogd.sample.mybatis.dao=DEBUG
注: 上述配置建議放在你的本地開(kāi)發(fā)環(huán)境配置文件中, 通常為 application-dev.properties, 關(guān)于 spring-boot 的 分環(huán)境配置 的
profile
機(jī)制, 如不熟悉請(qǐng)自行查閱網(wǎng)絡(luò)了解.
對(duì)應(yīng)工程代碼包結(jié)構(gòu)如下:
注: 我的代碼結(jié)構(gòu)下, mybatis 相關(guān)的類(lèi)放到了 dao 這個(gè)包下, 你的如果不是這樣, 可以根據(jù)自己的情況加以調(diào)整.
在上述配置下, 執(zhí)行以下測(cè)試:
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());
}
}
相應(yīng)的 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);
}
相應(yīng)的 sql 語(yǔ)句, 參數(shù)值及查詢(xún)的總數(shù)都會(huì)打印出來(lái):
14:48 ==> Preparing: select * from user where id = ?
14:48 ==> Parameters: 1(Integer)
14:48 <== Total: 1
輸出結(jié)果集
如果想進(jìn)一步輸出結(jié)果集, 則可以進(jìn)一步把日志級(jí)別提升到 TRACE
. 如下:
# log sql statement and result set
logging.level.net.xiaogd.sample.mybatis.dao=TRACE
警告: 可能導(dǎo)致大量的日志輸出, 非必要情況下不要啟用, 且僅可以在本地開(kāi)發(fā)環(huán)境調(diào)試情況下啟用!
對(duì)于下述的數(shù)據(jù)表:
最終的輸出如下:
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, 根用戶(hù)
17:36 <== Total: 2
可以看到字段及每行的值都被打印出來(lái)了.
遺留問(wèn)題
當(dāng)然了, 上述在輸出 sql 語(yǔ)句時(shí)還有一個(gè)問(wèn)題, 就是在有參數(shù)的情況下, 這個(gè)還不是最終的 sql, 而是類(lèi)似于 jdbc 中的那種 prepare statement:
select * from user where id = ?
可以看到參數(shù)的值是用一個(gè)問(wèn)號(hào)占位符代替的, 真正的參數(shù)值輸出到了另一行.
如果要真的拷貝到數(shù)據(jù)庫(kù)查看工具里執(zhí)行, 比如 navicat 或者 mysql workbench 抑或是最簡(jiǎn)單的 mysql console 中, 我們還是得自行替換及拼湊最終的 sql.
雖然多數(shù)情況下這也不是特別麻煩, 但在特別多參數(shù)的情況下, 如果你發(fā)現(xiàn)執(zhí)行結(jié)果不對(duì), 用眼睛看輸出的參數(shù)值似乎也沒(méi)有問(wèn)題, 自行去拼湊就有點(diǎn)麻煩了, 能否直接輸出最終的 sql 呢? 也是有方式的, 我們將在下一篇再介紹這種方式.文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-723081.html
參考文檔
更多打印 sql 日志相關(guān)的配置, 請(qǐng)參考其官網(wǎng): https://mybatis.org/mybatis-3/logging.html文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-723081.html
到了這里,關(guān)于配置 mybatis 打印出執(zhí)行的 sql 及返回的結(jié)果集的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!