Mybatis 动态SQL

本文介绍了动态SQL在MyBatis中的应用,通过实例展示了如何使用if、choose、trim和foreach等元素来动态构建SQL,提升查询灵活性。

什么是动态SQL?

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

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

搭建环境

  1. 创建一个普通项目

  2. 导包

  3. 编写数据库

    CREATE TABLE `blog`(
    `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;
    
  4. 编写实体类

    package pojo;
    
    import lombok.Data;
    
    import java.util.Date;
    
    @Data
    public class Blog {
        private String id;
        private String title;
        private String author;
        private Date createTime;
        private int views;
    }
    
    
  5. 编写接口

    package dao;
    
    import pojo.Blog;
    
    import java.util.List;
    import java.util.Map;
    
    public interface BlogMapper {
        List<Blog> getUsers(Map<String,Object> map);
    }
    
    

if

  1. 编写接口Mapper配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="dao.BlogMapper">
        <select id="getUsers" parameterType="map" resultType="Blog">
            select * from blog where 1=1
            <if test="title!=null">
                and title=#{title}
            </if>
            <if test="author!=null">
                and author=#{author}
            </if>
        </select>
    </mapper>
    
  2. 测试

    import dao.BlogMapper;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import pojo.Blog;
    import utils.IDutils;
    import utils.MybatisUtils;
    
    import java.util.Date;
    import java.util.HashMap;
    
    public class MyTest {
        @Test
        public void addBlogTest(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            HashMap<String, Object> map = new HashMap<>();
            map.put("title","Java");
    
            mapper.getUsers(map);
    
            sqlSession.commit();
            sqlSession.close();
        }
    }
    
    

choose(when,otherwise)

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.BlogMapper">
    <select id="getUsers" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>
            </choose>
        </where>
    </select>
</mapper>

trim(where,set)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.BlogMapper">
    <select id="getUsers" parameterType="map" resultType="Blog">
        select * from blog where 1=1
        <if test="title!=null">
            and title=#{title}
        </if>
        <if test="author!=null">
            and author=#{author}
        </if>
    </select>
</mapper>

我们看这个,可以看到我们写了一个 where 1=1 这是为了我们能够正确的查询,但是我们实际开发中肯定不希望有这种语句,然后就出现了where标签,where能够在where标签体内的条件至少满足一个的时候为我们自动添加where,且如果“and和or”前面是where的话,可以自动去掉“and和or”

set标签则是处理update语句的,看下面这条正常Sql语句

update tablename set password=#{password},name=#{name} where id=#{id}

我们的条件分割的中间是有逗号的,而set的作用就是将set给我们前置,然后去掉多余的逗号,也就是说如果在“name=#{name}”的后面还有逗号的话,set标签会帮我们去掉

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.BlogMapper">
    <update id="updateBlog" parameterType="map" >
        update user 
        <set>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
        </set>
            where id=#{id}
    </update>
</mapper>

trim就是用来定制where和set的,现在用的不多

定制where,如果where后面的语句前缀是and或者or则去除

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

定制set,如果set后面的语句后面有多余的逗号则去除

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

多的请自己去了解,这里不在多说

foreach

foreach就是用来遍历一个集合的,使用起来也非常简单,假如我们有下面一样的需求,查出用户表中的1、2、3个用户

select * from user where (id=1 or id=2 or id=3)

但是可以看到我们的是id有三个值,应该怎么做呢,这个时候就要用到我们的foreach了

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

这里解读一下foreach各个属性的作用

  • item------------>代表集合中的每一个元素
  • index------------>代表集合中的每一个元素的下标
  • collection------------>集合的名称
  • open------------>前缀
  • separator------------>分隔符
  • close------------>后缀

然后写一下我们的需求

<select id="getBlogForeach" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <foreach collection="ids" item="id" index="index" open="and (" separator="or" close=")">
            id=#{id}
        </foreach>
    </where>
</select>

29道练习题

https://blog.youkuaiyun.com/qq_38616503/article/details/107149495

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值