MyBatis动态SQL表达式详解

作者:一个双子座的Java攻城狮 时间:2023-11-29 00:42:36 

动态 sql 简单来讲就是我们能通过条件的设置生成不同的 sql,MyBatis 中常用的动态 sql 表达式主要是有五种:

  • if

  • choose (when, otherwise)

  • trim, where, set

  • foreach

  • sql

if

动态 sql 中最常见的场景是根据条件查询,比如要实现一个查询语句,当不传任何参数时查询所有用户,当传了 id 或者 name 时根据条件进行查询,就可以这样写:

<select id="selectUserByMap" parameterType="map" resultType="user">
   select * from user where 1=1
   <if test="id != null and id!=''">
       and id=#{id}
   </if>
   <if test="name != null and name!=''">
       and name=#{name}
   </if>
</select>

对应的 mapper 接口如下:

public interface UserMapper {
   List<User> selectUserByMap(Map<String,Object> param);
   void updateUser(Map<String,Object> param);
}

对应的 Java 代码如下:

Map<String,String> map=new HashMap<String, String>();
map.put("id","1");
map.put("name","javayz");
List<User> users = mapper.selectUserByMap(map);

当 map 中什么都不传时,sql 语句变为:

select * from user where 1=1

当传了 id 或 name 时,分别执行对应的查询。

choose when otherwise

choose 的使用很像 Java 中的 switch 语法,当满足第一个 when 条件时,就不去看后续的条件,如果条件都不满足,则执行 otherwise:

<select id="selectUserByChoose" parameterType="map" resultType="user">
   select * from user where 1=1
   <choose>
       <when test="id != null">
           and id=#{id}
       </when>
       <when test="name != null">
           and name=#{name}
       </when>
       <otherwise>
           and 1=1
       </otherwise>
   </choose>
</select>

trim where set

还记得前面的语法中都写了 where 1=1 吗,至于为什么这样写,目的在于让语法能顺利执行,以 if 语句为例:如果不写 1=1,语法就会变成下面这样:

<select id="selectUserByMap" parameterType="map" resultType="user">
   select * from user where
   <if test="id != null">
       id=#{id}
   </if>
   <if test="name != null">
       and name=#{name}
   </if>
</select>

这个时候如果满足了第一个 if 条件,那不会有问题,但是如果只满足第二个条件,语句就会变成:

select * from user where and name=?

语法直接报错。

MyBatis 提供了一种标签来代替 1=1 的写法,where 标签只会在子元素返回任何内容的情况下才插入 &ldquo;WHERE&rdquo; 子句。而且,若子句的开头为 &ldquo;AND&rdquo; 或 &ldquo;OR&rdquo;,where 元素也会将它们去除。

<select id="selectUserByMap" parameterType="map" resultType="user">
   select * from user
   <where>
       <if test="id != null">
           and id=#{id}
       </if>
       <if test="name != null">
           and name=#{name}
       </if>
   </where>
</select>

set 的语法和 where 类似,在更新时会用到 set:

<update id="updateUser" parameterType="map">
   update user
   <set>
       <if test="name != null">name =#{name},</if>
   </set>
   where id = #{id}
</update>

使用 where 时会用自动去替换掉 and 或者 or,而使用 set 时会动态地在行首插入 SET 关键字,并会删掉额外的逗号。

使用 trim 可以用于去除拼接 sql 时的 and、or 关键字或者逗号等等。

之前使用 where 标签去除了最开始的 and 关键字,用 trim 也同样可以实现:

<select id="selectUserByMap" parameterType="map" resultType="map">
   select * from user
   <trim prefix="where" prefixOverrides="and">
       <if test="id != null">
           and id=#{id}
       </if>
       <if test="name != null">
           and name=#{name}
       </if>
   </trim>
</select>

foreach

foreach 在需要对集合进行遍历的场景中使用很广泛,尤其是在 in 语句中,比如下面这条语句:

select * from user where id in (1,2,3,4)

通过 foreach 实现方式如下,foreach 中的 ids 可以是参数传入的一个 List 集合:

<select id="selectUserByForeach" parameterType="map" resultType="User">
   select * from user where id in
       <foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
           #{id}
       </foreach>
</select>

sql片段

通过 sql 片段标签,可以将重复的 sql 提取出来,使用时通过 include 引用即可。

<sql id="select_user_where">
   <if test="id != null and id!=''">
       and id=#{id}
   </if>
   <if test="name != null and name!=''">
       and name=#{name}
   </if>
</sql>
<select id="selectUserByMap" parameterType="map" resultType="user">
   select * from user where 1=1
   <include refid="select_user_where">
</select>

来源:https://blog.csdn.net/weixin_64061088/article/details/128450087

标签:MyBatis,动态,SQL,表达式
0
投稿

猜你喜欢

  • Spring Batch入门教程篇

    2022-02-15 01:53:01
  • 深入理解java动态代理的两种实现方式(JDK/Cglib)

    2023-11-26 13:29:52
  • Mybatis通过Spring完成代理类注入的流程分析

    2023-10-25 00:55:55
  • C#使用webbrowser的常见用法实例

    2023-06-14 13:57:45
  • 这一次搞懂Spring事务是如何传播的

    2022-12-27 07:06:53
  • C# Winform选项卡集成窗体详解

    2021-08-12 17:13:55
  • mybatis if标签判断不生效的解决方法

    2023-11-28 12:30:49
  • Android中oncreate中获得控件高度或宽度的实现方法

    2023-09-27 05:32:12
  • 基于JavaMail实现邮件发送

    2022-06-21 02:28:06
  • Mybatis如何配置连接池

    2021-10-22 03:06:47
  • Java中BeanUtils.copyProperties基本用法与小坑

    2021-11-04 22:09:01
  • VisualStudio Community2019在安装的过程中无法进入安装界面的解决方法

    2023-02-09 11:24:34
  • java中的前++和后++的区别示例代码详解

    2023-09-01 10:15:01
  • Java中的Object类详细介绍

    2023-11-23 23:18:46
  • Java递归寻路实现,你真的理解了吗

    2022-09-17 02:24:34
  • C#使用NPOI将List数据导出到Excel文档

    2022-12-18 12:28:09
  • Feign如何自定义注解翻译器

    2022-11-09 07:05:04
  • Android 设置颜色的方法总结

    2023-12-14 16:41:57
  • Spring P标签的使用详解

    2021-09-28 22:24:14
  • Android时间对话框TimePickerDialog详解

    2022-08-23 05:50:06
  • asp之家 软件编程 m.aspxhome.com