MyBatis 操作数据库:动态SQL

目录

1. <if>标签

2. <trim>标签

3.  <where>标签

4. <set>标签

5. <foreach>标签

6. <include>标签


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

官方文档:Mybatis动态SQL

1. <if>标签

在某些注册用户界面,有必填字段和非必填字段两种,那如果在添加用户的时候有不确定的字段传入,程序应该如何实现呢? 这个时候就需要使用动态标签来判断了,比如添加的时候性别 gender 为非必填字段,具体实现为:

接口定义:

Integer insertUserByCondition(UserInfo userInfo);

Mapper.xml

<insert id="insertUserByCondition">
   INSERT INTO userinfo (
   username,
   `password`,
   age,
   <if test="gender != null">
      gender,
   </if>
   phone)
   VALUES (
   #{username},
   #{age},
   <if test="gender != null">
      #{gender},
   </if>
   #{phone})
</insert>
注意 test 中的 gender,是传入对象中的属性,不是数据库字段。

注解方式实现(不推荐,因为麻烦且容易出错):

@Insert("<script>" +
        "INSERT INTO userinfo (username,`password`,age," +
        "<if test='gender!=null'>gender,</if>" +
        "phone)" +
        "VALUES(#{username},#{age}," +
        "<if test='gender!=null'>
           #{gender},
        </if>" +
        "#{phone})"+
        "</script>")
Integer insertUserByCondition(UserInfo userInfo);

2. <trim>标签

如果选填项有多个字段,就会考虑使用标签结合标签,对多个字段都采用动态生成的方式。

标签中有如下属性:

  • prefix:表示整个语句块,以prefix的值作为前缀
  • suffix:表示整个语句块,以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除掉的前缀

  • suffixOverrides:表示整个语句块要去除掉的后缀 
Mapper.xml 的插入语句为:
<insert id="insertUserByCondition">
    INSERT INTO userinfo
    <trim prefix="(" suffix=")" suffixOverrides=",">
       <if test="username !=null">
           username,
       </if>
       <if test="password !=null">
           `password`,
       </if>
       <if test="age != null">
           age,
       </if>
       <if test="gender != null">
           gender,
       </if>
       <if test="phone != null">
           phone,
       </if>
     </trim>

     VALUES
     <trim prefix="(" suffix=")" suffixOverrides=",">
       <if test="username !=null">
           #{username},
       </if>
       <if test="password !=null">
           #{password},
       </if>
       <if test="age != null">
           #{age},
       </if>
       <if test="gender != null">
           #{gender},
       </if>
       <if test="phone != null">
           #{phone}
       </if>
     </trim>
</insert>

注解方式同上,此处及下面不再举例。

在以上 sql 动态解析时,会将第一个部分做如下处理:
  • 基于 prefix 配置,开始部分加上 (
  • 基于 suffix 配置,结束部分加上 )
  • 多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于suffixOverrides 配置去掉最后一个
  • 注意 <if test="username !=null"> 中的 username 是传入对象的属性

3. <where> 标签

当筛选条件有多个的时候会动态组装where条件。

举例:传入的用户对象,根据属性做where条件查询,用户对象中属性不为 null 的,都为查询条件。 如 username 为 "a",则查询条件为 where username="a"

原有SQL:

SELECT  * FROM userinfo WHERE
   age = 18
   AND gender = 1
   AND delete_flag =0;
接口定义:
List<UserInfo> queryByCondition();

Mapper.xml实现:

<select id="queryByCondition" resultType="com.example.demo.model.UserInfo">
    select id, username, age, gender, phone, delete_flag, create_time, 
update_time
  from userinfo
  <where>
       <if test="age != null">
           and age = #{age}
       </if>
       <if test="gender != null">
           and gender = #{gender}
       </if>
       <if test="deleteFlag != null">
           and delete_flag = #{deleteFlag}
       </if>
    </where>
</select>
<where> 只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头AND或 OR。
以上标签也可以使用  <trim prefix="where" prefixOverrides="and"> 替换, 但是此种情况下, 当子元素都没有内容时, where关键字也会保留。

4. <set>标签

举例:根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容。
接口定义: 根据传入的用户 id 属性,修改其他不为 null 的属性。
Integer updateUserByCondition(UserInfo userInfo);

Mapper.xml:

<update id="updateUserByCondition">
      update userinfo
      <set>
           <if test="username != null">
             username = #{username},
           </if>
           <if test="age != null">
             age = #{age},
           </if>
           <if test="deleteFlag != null">
             delete_flag = #{deleteFlag},
           </if>
       </set>
       where id = #{id}
</update>

<set> :动态的在SQL语句中插入set关键字,并会删掉额外的逗号。(用于update语句中)

以上标签也可以使用 <trim prefix="set" suffixOverrides=","> 替换。

5. <foreach>标签

对集合进行遍历时可以使用该标签。标签有如下属性:
  • collection:绑定方法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的每一个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串
举例:根据多个userid, 删除用户数据
接口方法:
void deleteByIds(List<Integer> ids);
ArticleMapper.xml 中新增删除 sql:
<delete id="deleteByIds">
     delete from userinfo
     where id in
     <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
     </foreach>
</delete>

6. <include>标签

在xml映射文件中配置的SQL,有时可能会存在很多重复的片段,此时就会存在很多冗余的代码:

可以对重复的代码片段进行抽取,将其通过 <sql> 标签封装到一个SQL片段,然后再通过 <include> 标签进行引用。

  • <sql> :定义可重用的SQL片段
  • <include> :通过属性refid,指定包含的SQL片段
<sql id="allColumn">
  id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>
通过 <include> 标签在原来抽取的地方进行引用。操作如下:
<select id="queryAllUser" resultMap="BaseMap">
    select
    <include refid="allColumn"></include>
    from userinfo
</select>
<select id="queryById" resultType="com.example.demo.model.UserInfo">
    select
    <include refid="allColumn"></include>
    from userinfo where id= #{id}
</select>
  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值