mybatis学习(十一、动态SQL)

十一、动态SQL

什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

搭建环境

创建一张表

CREATE TABLE `bolg` (
  `id` varchar(50) NOT NULL COMMENT ‘博客id‘,
  `title` varchar(100) NOT NULL COMMENT ‘博客标题‘,
  `author` varchar(30) NOT NULL COMMENT ‘博客作者‘,
  `create_time` datetime NOT NULL COMMENT ‘创建时间‘,
  `views` int(30) NOT NULL COMMENT ‘浏览量‘
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建一个基础工程

  1. 导包

  2. 编写配置文件

  3. 编写实体类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Blog {
        private String id;
        private String title;
        private String author;
        private Date createTime;//设置驼峰命名映射
        private int views;
    }
    
  4. 编写实体类对应的Mapper接口和Mapper.xml文件

    public interface BlogMapper {
    
        //插入数据
        int addBlog(Blog blog);
    }
    
    <insert id="addBlog" parameterType="blog">
        insert into mybatis.bolg (id, title, author, create_time, views)
        values (#{id}, #{title}, #{author}, #{createTime}, #{views});
    </insert>
    

IF

可以实现SQL语句的判断拼接

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

比如此时,如果不传递title和author,那么会查出全部的数据。

ps:使用where标签

choose(when, otherwise)

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="queryBlog" parameterType="map" resultType="blog">
    SELECT * FROM mybatis.bolg
    <where>
        <choose>
            <when test="title != null">
                AND title = #{title}
            </when>
            <when test="author != null">
                AND author = #{author}
            </when>
            <otherwise>
                AND views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

trim(where, set)

set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)

<update id="updateBlog" parameterType="blog">
    update mybatis.bolg
    <set>
        <if test="title != null">
            title=#{title},
        </if>
        <if test="author">
            author=#{author},
        </if>
        <if test="views != 0">
            views=#{views},
        </if>
    </set>
    where id=#{id}
</update>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

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

若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:

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

注意这里我们删去的是后缀值,同时添加了前缀值。

如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

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

prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

所谓动态SQL,本质上就是SQL语句,只不过可以在SQL层面上执行一些逻辑代码

SQL片段

有时候我们可能将一些功能的部分抽取出来,方便复用

<sql id="sql">
    select * from mybatis.bolg;
</sql>

<select id="queryBlog" parameterType="map" resultType="blog">
    <!--引用sql片段-->
	<include refid="sql"></include>
</select>

  1. 使用SQL标签抽取公共的部分
  2. 在需要使用的地方使用include标签即可

注意事项

  • 最好通过单表来定义SQL片段
  • 不要存在where标签

forEach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM Bolg b
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

实际使用:

<!--我们现在传递一个万能的Map,这个map中可以存在一个集合-->
<select id="queryBlogForEach" parameterType="map" resultType="blog">
    select * from mybatis.bolg
    <where>
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id=#{id}
        </foreach>
    </where>
</select>

动态SQL就是在拼接SQL语句,我们要保证SQL的正确性,按照SQL的格式,去排列组合就可以了

建议:

  • 先在mysql中写出完整版的SQL语句,再去修改成为动态SQL实现通用即可

mybatis学习(十一、动态SQL)

上一篇:SpringMVC-mybatis-plus-基于aop实现动态连接多个数据库


下一篇:Oracle OCP 19c 认证1Z0-083考试题库(第8题)