说明:之前介绍过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一些补充用法