MyBatis XML 条件语句

if 语句

  1. <update id="update" parameterType="com.lzx.comment.dataobject.UserDO">
  2. update user set nick_name=#{nickName},gmt_modified=now() where id=#{id}
  3. </update>

如果nickNamenull,这样修改是不是出问题了,我们知道nickName字段不应该为 null
结合条件语句来执行

  1. <update id="update" parameterType="com.lzx.comment.dataobject.UserDO">
  2. update user set
  3. <if test="nickName != null">
  4. nick_name=#{nickName},gmt_modified=now()
  5. </if>
  6. where id=#{id}
  7. </update>

set 语句

上面的 update 语句中,如果nickName 为 null ,SQL会变成

  1. update user set where id=?

这是错误的SQL语句。
实际开发中结合set来编写update

<update id="update" parameterType="com.lzx.comment.dataobject.UserDO">
  update user
  <set>
    <if test="nickName != null">
      nick_name=#{nickName},gmt_modified=now()
    </if>
  </set>
   where id=#{id}
</update>

if+select

很多时候我们的查询条件都是动态的,比如我们想迷糊查询某个时间后注册的用户。

List<UserDO> search(@Param("keyWord")String keyWord,
      @Param("time")LocalDateTime time);

XML

<select id="search" resultMap="userResultMap">
  select * from user where
    <if test="keyWord != null">
      user_name like CONCAT('%',#{keyWord},'%')
        or nick_name like CONCAT('%',#{keyWord},'%')
    </if>
    <if test="time != null">
      and  gmt_created <![CDATA[ >= ]]> #{time}
    </if>
</select>

=、<、<=、>、>=、& 这类的表达式会导致MyBatis解析失败,所以我们需要使用<![CDATA[ >= ]]> 来包围住。
由于这里的参数是LocalDateTime 我们学习过Http的知识应该知道,URL传递过来的参数都是字符串类型。所以这里API调用有点特殊。

import com.lzx.comment.dao.UserDAO;
import com.lzx.comment.dataobject.UserDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@Controller
public class UserController {

    @Autowired
    private UserDAO userDAO;

    @GetMapping("/user/search")
    @ResponseBody
    public List<UserDO> search(@RequestParam("keyWord") String keyWord,
    @RequestParam("time")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    LocalDateTime time) {
        return userDAO.search(keyWord, time);
    }
}

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 注解,把字段串转化为日期类型。

where 语句

上述SQL执行的时候有两种例外:

  • keyword 为 null ,SQL会变成

    select * from user where
     and  gmt_created >= ?
    
  • keyword ,time 都为 null,SQL变为

    select * from user where
    

    把 SQL where 子句改为MyBatis XML 的where 子句,就可以解决这种问题。

    <select id="search" resultMap="userResultMap">
    select * from user
     <where>
        <if test="keyWord != null">
            user_name like CONCAT('%',#{keyWord},'%')
              or nick_name like CONCAT('%',#{keyWord},'%')
        </if>
        <if test="time != null">
          and  gmt_created <![CDATA[ >= ]]> #{time}
        </if>
     </where>
    </select>
    

    其他条件语句

  • choose

  • when
  • otherwise
  • trim

    MyBatis 循环语句

    foreach

    应用需求:批量插入,SQL in 查询
    DAO方法 ```java @Mapper public interface UserDAO {

    int batchAdd(@Param(“list”) List userDOs);

}

```xml
<insert id="batchAdd" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (user_name, pwd, nick_name,avatar,gmt_created,gmt_modified)
    VALUES
    <foreach collection="list" item="it" index="index" separator =",">
        (#{it.userName}, #{it.pwd}, #{it.nickName}, #{it.avatar},now(),now())
    </foreach >
</insert>
  • useGeneratedKeys 取值范围truefalse 默认值是:false。 含义:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。
  • keyPropertyidkey值,设置完以后我们就可以在前端获取到该自增ID的值。

foreach相当于执行了Javafor循环。
_foreach_ 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 ListSet等)、Map 对象或者数组对象作为集合参数传递给 _foreach_。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键(索引从0开始),item 是值。

  • collection 指定集合的上下文参数名称,比如这里的list 对应的是@Param("l``ist``")
  • separator遍历每条记录并添加分隔符。

上面的SQL语句最终执行会变成

INSERT INTO user (user_name, pwd, nick_name,avatar,gmt_created,gmt_modified)
    VALUES
    (?, ?, ?,?,now(),now()),
    (?, ?, ?,?,now(),now()),
    (?, ?, ?,?,now(),now())

查询多个用户:

@Mapper
public interface UserDAO {

    List<UserDO> findByIds(@Param("ids") List<Long> ids);

}
<select id="findByIds" resultMap="userResultMap">
    select * from user
    <where>
        id in
        <foreach item="item" index="index" collection="ids"
                    open="(" separator="," close=")">
            #{item}
        </foreach>
    </where>
</select>
  • open

表示节点开始是自定义的分隔符

  • close

表示节点结束时自定义的分隔符

select * from user where id in (?,?,?)

疑问

前端该如何提交集合/数组到后端?
image.png
fetch请求
ajax请求