說明:之前介紹過MyBatis的用法,像 用注解和Mapper.xml操作數據庫、在Mapper.xml里寫動態SQL。最近在一次用MyBatis批量更新數據庫對象的場景中,意識到對MyBatis的一些標簽用法不太熟悉,所以去 MyBatis官網 看了一些文檔,基于此,本文介紹一些可能會用到的MyBatis用法。
$ 占位符
通常我們會使用#{}
表示占位符,即該位置的值使用傳遞的參數,在運行SQL拼接時,會用 ?
占位,在執行SQL的時候才會將我們的參數替換執行,不會有SQL注入的風險。如下:
(controller層)
/*** 查詢用戶* @param id* @return*/@GetMapping("/getUser/{id}")public String getUser(@PathVariable("id") String id){return userMapper.getUser(id).toString();}
(mapper層)
@Select("select * from user where id = #{id}")User getUser(String id);
控制臺打印的執行日志:
換成 ${}
再看下:
@Select("select * from tb_user where id = ${id}")User getUser(String id);
查看控制臺可以看到,執行過程是直接將參數進行拼接的;
這么說,那還需要這個干什么,直接用#{}
不就行了。我在查看官網文檔時,文檔提到了一個用法,可以動態查詢數據庫表中的某列字段,如下:
@Select("select ${field} from tb_user where id = #{id}")User getUser(String field, String id);
field表示User表中的任意字段,該接口的作用就是根據ID查詢User表中的任意字段值,該字段可用前端、或者Service層判斷后傳入;
(field傳username,表示根據ID查詢username)
(field傳password,表示根據ID查詢password)
另外,如果可以你還可以在 order by
后面方放一個 ${sortField}
(根據某字段排序),讓結果集的排序可根據前端或者Service層來動態的控制,非常靈活。這也算是$ 占位符
的一抹光輝。
使用上的注意事項,官網中有一段說明,如下:
script 標簽
我們都知道,使用Mabatis框架操作數據庫有兩種方式,一種是在Mapper中的接口上寫注解,注解里寫SQL語句,就像上面那樣;一種是在對應的Mapper.xml中寫SQL,關聯到具體的Mapper接口,如下:
(namespace里寫Mapper的全限定類名,mapper標簽里面寫對應類里的接口,id為方法名,resultType為結果集封裝的對象的全限定類名)
<mapper namespace="com.hezy.mapper.UserMapper"><select id="getUser" resultType="com.hezy.pojo.User">select *from tb_userwhere id = #{id}</select>
</mapper>
關于這兩種方式該怎么選擇,官網中也有一段非常優雅的描述,如下:
而 script標簽
的作用,就是把Mapper.xml中的動態SQL寫在注解里,如下,根據ID更新數據,在Mapper.xml我們是這么寫的。
<update id="updateUserById">update tb_user<set><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if></set>where id = #{id}</update>
如果你不想寫在Mapper.xml里面(雖然不知道你為什么不想),就可以使用 script標簽
我們可以把它寫在注解里,如下:
@Update("<script>" +"update tb_user " +"<set>" +"<if test='username != null'>username = #{username},</if>" +"<if test='password != null'>password = #{password}</if>" +"where id = #{id}" +"</set>" +"</script>")void updateUserById(User user);
雖然有點麻煩,我調試了一會兒,但效果是一樣
trim 標簽
在介紹trim標簽
前,先介紹我們經常會用到的兩個標簽:<set>標簽 和 <where>標簽
;
<set>標簽
在更新數據時使用,如下:
<update id="updateUserById">update tb_user<set><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if></set>where id = #{id}</update>
它的作用是可以在拼接SQL時,刪掉多于的逗號(,),比如上面這段動態SQL,當password值不為空時,拼接出來的SQL是下面這樣的:
update tb_user set username = 'zhangsan_fix', password = '123456_fix', where id = '1'
執行會報錯;
<where>標簽
在復雜的條件查詢時使用,如下:
<select id="queryUser" resultType="com.hezy.pojo.User">select * from tb_user<where><if test="id != null and id != ''">and id = #{id}</if><if test="username != null and username != ''">and username = #{username}</if><if test="password != null and password != ''">and password = #{password}</if></where></select>
它的作用是可以在拼接SQL時,刪掉多于的 and
或者 or
,像上面的動態SQL,如果id不為空,就會在where
后面拼接一個莫名其妙的and
,這樣的SQL同樣是執行不成功的。
而 trim 標簽
的作用是,可以自定義選擇在哪個關鍵字附近添加或刪減什么字符。trim 標簽屬性如下:
-
prefix:前面拼接的內容;
-
suffix:后面拼接的內容;
-
prefixOverrides:去除的前綴內容;
-
suffixOverrides:去除的后綴內容
trim 標簽可以起到<set>標簽 和 <where>標簽
相同的作用,如下:
(trim標簽里面的語句,前面加個 set
,末尾多于的逗號去掉,等同于 <set>標簽
)
<update id="updateUserById">update tb_user<trim prefix="set" suffixOverrides=","><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if></trim>where id = #{id}</update>
控制臺打印的日志信息
(trim標簽里面的語句,前面加個 where
,去掉前面多于的and
或者 or
,等同于 <where>標簽
)
<select id="queryUser" resultType="com.hezy.pojo.User">select * from tb_user<trim prefix="where" prefixOverrides="and |or "><if test="id != null and id != ''">and id = #{id}</if><if test="username != null and username != ''">and username = #{username}</if><if test="password != null and password != ''">and password = #{password}</if></trim></select>
控制臺打印的日志信息
官網中有說明,and |or
這里的空格是必要的,但我去掉之后執行時沒有問題的,或許是考慮在一些特殊的場景沒有空格是會有問題的。我想不到,有讀者想得到請告訴我(do ze)。
總結
本文介紹了MyBatis一些補充用法