MyBatis 中為什麼不建議使用 where 1=1?
最近接手了一個老項目,「愉悅的心情」自然無以言表,做開發的朋友都懂,這裡就不多說了,都是淚…
接手老項目,自然是要先熟悉一下業務程式碼,然而在翻閱 mapper 文件時,發現了一個比較詭異的事情。這裡給出簡化後的業務程式碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="list" resultType="com.example.demo.model.User">
select * from user
where 1=1
<if test="name!=null">
and name=#{name}
</if>
<if test="password!=null">
and password=#{password}
</if>
</select>
</mapper>
機智的小夥伴可能已經看出了問題,在眾多 mapper 中發現了一個相同的想像,幾乎所有的 mapper 中都包含了一個無用的拼接 SQL:where 1=1。作為一個幾乎有程式碼潔癖症的人,自然是忍不住動手改造一番了。
錯誤的改造方式
既然是去掉 where 1=1,那最簡單的方式就是將它直接從程式碼中刪除了,如下程式碼所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="list" resultType="com.example.demo.model.User">
select * from user
where
<if test="name!=null">
name=#{name}
</if>
<if test="password!=null">
and password=#{password}
</if>
</select>
</mapper>
以上程式碼刪除了 1=1,並且把第一個 name 查詢中的 and 去掉了,以防 SQL 查詢報錯。
但這樣就沒問題了嗎?我們直接來看結果,當包含參數 name 查詢時,結果如下:
一切順利成章,完美的一塌糊塗。
然而,當省略 name 參數時(因為 name 為非必要參數,所以可以省略),竟然引發了以下異常:
又或者只有 password 查詢時,結果也是一樣:
都是報錯資訊,那腫么辦呢?難不成把 1=1 恢復回去?
正確的改進方式
其實不用,在 MyBatis 中早已經想到了這個問題,我們可以將 SQL 中的 where 關鍵字換成 MyBatis 中的
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="list" resultType="com.example.demo.model.User">
select * from user
<where>
<if test="name!=null">
and name=#{name}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
</select>
</mapper>
程式碼改造完成之後,接下來我們來測試一下所有的請求場景。
不傳任何參數的請求
此時我們可以不傳遞任何參數(查詢所有數據),如下圖所示:
生成的 SQL 語句如下:
傳遞 1 個參數的請求
也可以傳遞 1 個參數,根據 name 進行查詢,如下圖所示:
生成的 SQL 如下圖所示:
也可以只根據 password 進行查詢,如下圖所示:
生成的 SQL 如下圖所示:
傳遞 2 個參數的請求
也可以根據 name 加 password 的方式進行聯合查詢,如下圖所示:
生成的 SQL 如下圖所示:
用法解析
我們驚喜的發現,在使用了
首先,
總結
在 MyBatis 中,建議盡量避免使用無意義的 SQL 拼接 where 1=1,我們可以使用
關注公眾號「Java中文社群」查看更多 MyBatis 和 Spring Boot 的系列文章。