说明:之前介绍过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_user
where 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 标签
的作用是,可以自定义选择在包裹的SQL片段前面/后面添加内容,并且删减掉指定的前缀或后缀。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一些补充用法