信息发布→ 登录 注册 退出

Mybatis超级强大的动态SQL语句大全

发布时间:2026-01-11

点击量:
目录
  • 1. If 语句
  • 2. Where语句
    • 2.1 和 where 元素等价的自定义 trim 元素
  • 3. Set语句
    • 3.1 与 set 元素等价的自定义 trim 元素
  • 4. Choose语句
    • 5. Foreach语句
      • 6. SQL片段
        • 7. Bind元素
          • 附:MyBatis配置动态SQL语句
            • 总结

              1. If 语句

              需求:根据作者名字和博客名字来查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询

              <!--需求1:
              根据作者名字和博客名字来查询博客!
              如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
              select * from blog where title = #{title} and author = #{author}
              -->
              <select id="queryBlogIf" parameterType="map" resultType="blog">
                  select * from blog where
                  <if test="title != null">
                      title = #{title}
                  </if>
                  <if test="author != null">
                      and author = #{author}
                  </if>
              </select>
              

              这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title},但是如果title为空呢?那么查询语句为 select * from user where and author=#{author},这是错误的SQL 语句,如何解决呢?请看下面的 where 语句!

              2. Where语句

              修改上面的SQL语句:

              <select id="queryBlogIf" parameterType="map" resultType="blog">
                  select * from blog
                  <where>
                      <if test="title != null">
                          title = #{title}
                      </if>
                      <if test="author != null">
                          and author = #{author}
                      </if>
                  </where>
              </select>
              

              where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

              如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。

              2.1 和 where 元素等价的自定义 trim 元素

              <trim prefix="WHERE" prefixOverrides="AND |OR ">
                ...
              </trim>
              

              3. Set语句

              同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,
              我们怎么处理呢?

              <!--注意set是用的逗号隔开-->
              <update id="updateBlog" parameterType="map">
                  update blog
                  <set>
                      <if test="title != null">
                          title = #{title},
                      </if>
                      <if test="author != null">
                          author = #{author}
                      </if>
                  </set>
                  where id = #{id};
              </update>
              

              这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

              3.1 与 set 元素等价的自定义 trim 元素

              <trim prefix="SET" suffixOverrides=",">
                ...
              </trim>
              

              4. Choose语句

              有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose标签可以解决此类问题,类似于 Java 的 switch 语句

              <select id="queryBlogChoose" parameterType="map" resultType="blog">
                  select * from blog
                  <where>
                      <choose>
                          <when test="title != null">
                              title = #{title}
                          </when>
                          <when test="author != null">
                              and author = #{author}
                          </when>
                          <otherwise>
                              and views = #{views}
                          </otherwise>
                      </choose>
                  </where>
              </select>
              

              5. Foreach语句

              将数据库中前三个数据的id修改为1,2,3;

              需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

              <select id="queryBlogForeach" parameterType="map" resultType="blog">
                  select * from blog
                  <where>
                      <!--
                      collection:指定输入对象中的集合属性
                      item:每次遍历生成的对象
                      open:开始遍历时的拼接字符串
                      close:结束时拼接的字符串
                      separator:遍历对象之间需要拼接的字符串
                      select * from blog where 1=1 and (id=1 or id=2 or id=3)
                      -->
                      <foreach collection="ids" item="id" open="and (" close=")"
                      separator="or">
                          id=#{id}
                      </foreach>
                  </where>
              </select>
              

              6. SQL片段

              有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。

              提取SQL片段:

              <sql id="if-title-author">
                  <if test="title != null">
                      title = #{title}
                  </if>
                  <if test="author != null">
                      and author = #{author}
                  </if>
              </sql>
              

              引用SQL片段:

              <select id="queryBlogIf" parameterType="map" resultType="blog">
                  select * from blog
                  <where>
                      <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace-->
                      <include refid="if-title-author"></include>
                      <!-- 在这里还可以引用其他的 sql 片段 -->
                  </where>
              </select>
              

              注意:

              ①、最好基于 单表来定义 sql 片段,提高片段的可重用性

              ②、在 sql 片段中不要包括 where

              7. Bind元素

              bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:

              <select id="selectBlogsLike" resultType="Blog">
                <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
                SELECT * FROM BLOG
                WHERE title LIKE #{pattern}
              </select>
              

              附:MyBatis配置动态SQL语句

              CREATE DATABASE `mybatis_study`;
              
              USE `mybatis_study`;
              
              CREATE TABLE `user`(
                `user_id` INT(20) NOT NULL PRIMARY KEY,
                `user_name` VARCHAR(30) DEFAULT NULL,
                `password` VARCHAR(30) DEFAULT NULL
              )ENGINE = INNODB DEFAULT CHARSET = utf8;
              
              INSERT INTO `user` (`user_id`,`user_name`,`password`) VALUES
              (1, '张三', '123456'),
              (2, 'admin', 'admin'),
              (3, 'root', 'root');

              在 MyBatis 的 SQL映射文件中,有时候需要根据一些查询条件,来选择不同的SQL语句,如果每一个场景都重写SQL,很显然效率没有很高,而 MyBatis 的动态SQL很好的解决了这种问题,根据条件动态的处理 SQL, 特别简单的说就是,写一次SQL,但是根据分支等的跳转,在多个场景下也可以使用,例如:

              • 当查询条件由于参数不同而无法确定具体是什么,可以使用<where>标签包含
              • 在 <where> 可以使用 <if test="...."> 分条件进行处理,实现动态
              • <foreach>遍历标签,在用户中查询寻多个id,例如(12,16,17)

              在此之外,动态SQL同时结局了,在原生 JDBC 中需要拼接SQL语句时由于书写问题,而导致报错

              总结

              在线客服
              服务热线

              服务热线

              4008888355

              微信咨询
              二维码
              返回顶部
              ×二维码

              截屏,微信识别二维码

              打开微信

              微信号已复制,请打开微信添加咨询详情!