动态sql是Mybatis的强大功能之一,能够完成不同条件下不同的sql拼接。

标签

如图是gitee上创建仓库的页面:

可以分为两种字段,必填字段和非必填字段,在创建仓库时无法确定用户是否会传入”仓库介绍“字段,如果用户不填写,那么前端传过来的就是Null, 在sql中""和null是不相等的,因此需要使用标签来判断。

语法格式:

  • 中的test会产生一个boolean类型的结果,如果为true,那么执行if标签的内容;如果为false,那么不执行if里面的内容。
  • test中的参数,是传入对象的属性,不是数据库字段

咱们这里使用的数据表和前几篇一致,为articleinfo和userinfo表

需求:在用户注册环节,photo字段非必填。

photo字段可以标签,当photo字段不为空,则添加;为空就不添加。并且要注意 , 放的位置,不能跟着password后面,因为如果photo字段为空,就会造成sql语法错误

int addUser(Userinfo userinfo);
<insert id="addUser">insert into userinfo (username, password<if test="photo!=null">, photo</if>)values (#{username}, #{password}<if test="photo!=null">, #{photo}</if>)</insert>
@Testvoid addUser() {Userinfo userinfo = new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("2345");userinfo.setPhoto(null); //在sql中”“不等于NulluserMapper.addUser(userinfo);System.out.println(userinfo);}

标签

在用户注册的时候,只有一个photo字段是非必填项,如果所有字段都是非必填项,可以考虑使用标签结合标签,对多个字段都采取动态生成的方式。
标签中有如下属性:

  • prefix: 表示整个语句块,以prefix的值作为前缀
  • suffix: 表示整个语句块,以suffix为值作为后缀
  • prefixOverrides: 表示整个语句块要去除掉的前缀
  • suffixOverrides: 表示整个语句块要去除掉的后缀
int addUser2(Userinfo userinfo);
<insert id="addUser2" useGeneratedKeys="true" keyColumn="id">insert into userinfo<trim prefix="(" suffix=")" suffixOverrides=","><if test="username != null">username,</if><if test="password != null">password,</if><if test="photo != null">photo,</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="username != null">#{username},</if><if test="password != null">#{password},</if><if test="photo != null">#{photo},</if></trim></insert>
@Testvoid addUser2() {Userinfo userinfo = new Userinfo();userinfo.setUsername("王五");userinfo.setPassword("45667");userinfo.setPhoto(null);userMapper.addUser2(userinfo);System.out.println(userinfo);}


在上面的sql动态解析时,会将第一个做如下处理:

  1. 基于prefix,开始部分加上(
  2. 基于suffix,结束部分加上)
  3. 多个组织的语句都以,结尾,在最后拼接好的字符串是以,结尾,会基于suffixOverrides去掉最后一个,

标签

顾名思义和mysql中的where作用一样,都是用来条件查询。

需求:跟据前端提供的用户名和密码(都是非必传的参数)查询用户信息

List<Userinfo> selectByParam(@Param("username") String username, @Param("password") String password);
<select id="selectByParam" resultType="com.example.demo.entity.Userinfo">select * from userinfo<where><if test="username != null">username = #{username}</if><if test="password != null">and password = #{password}</if></where></select>
@Testvoid selectByParam() {List<Userinfo> list = userMapper.selectByParam(null, "admin");System.out.println(list);}

  • where标签通常需要配合if标签一起使用
  • where标签会删除最前面的and关键字(所以上面的例子中就把password前面的and关键字去除)
  • where标签如果里面没有内容,那么他不会生成where sql语句

标签

顾名思义和mysql的set作用一样,都是用来更新数据。

需求:前端传递Userinfo给后端(部分属性是非必填),请根据id修改用户信息

int update(Userinfo userinfo);
<update id="update">update userinfo<set><if test="username != null">username = #{username},</if><if test="password != null">password = #{password},</if><if test="photo != null">photo = #{photo}</if></set>where id = #{id}</update>
@Testvoid update() {Userinfo userinfo = new Userinfo();userinfo.setUsername("张三");userinfo.setPassword(null);userinfo.setPhoto("bbb.png");userinfo.setId(1);userMapper.update(userinfo);System.out.println(userinfo);}

  • set标签通常配合 if 标签一起使用
  • set标签会自动去除最后一个逗号

标签

顾名思义用来循环遍历的,标签有如下属性:

  • collection: 绑定方法参数中的集合,如List,Set,Map
  • item: 遍历时的对象
  • open:语句块开头的字符串
  • close: 语句块结束的字符串
  • separator: 每次遍历之间间隔的字符串

需求:根据多个文章id删除文章数据

int dels(List<Integer> list);
<delete id="dels">delete from userinfowhere id in<foreach collection="list" item="item" open="(" close=")" separator=",">#{item}</foreach></delete>
@Testvoid dels() {List<Integer> list = new ArrayList<>();list.add(1);list.add(3);int dels = userMapper.dels(list);Assertions.assertEquals(2, dels);}