MyBatis中动态SQL IF、Choose、Trim、Foreach

一、MyBatis中的动态SQL

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

MyBatis中动态SQL元素

  1. if
  2. choose(when,otherwise)
  3. trim(where,set)
  4. foreach
  5. sql片段

1、创建基本环境

  1. 创建数据库表blog

    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
    
  2. 创建实体类Blog

    对应表blog的字段,创建Blog类

    package org.westos.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import java.util.Date;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Blog {
        private String id;
        private String title;
        private String author;
        private Date createTime;
        private int views;
    }
    
  3. 创建对应的接口BlogMapper

    package org.westos.mapper;
    
    import org.westos.pojo.Blog;
    import java.util.Map;
    
    public interface BlogMapper {
        //添加博客
        public void addBlog(Blog blog);
    }
    
  4. 创建对应的xml配置文件BlogMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.westos.mapper.BlogMapper">
    
        <insert id="addBlog" parameterType="org.westos.pojo.Blog">
           INSERT INTO `blog`(`id`,`title`,`author`,`create_time`,`views`) VALUES (#{id},#{title},#{author},#{createTime},#{views})
        </insert>
    </mapper>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zWr0PEkL-1582304351170)(assets/1582271343949.png)]

  5. 开启下划线转驼峰命名

    因为数据库表中字段命名一般使用下划线隔开单词,而Java变量使用驼峰命名,所以在多单词命名时,数据库字段名就会和Java属性名不一致,这个时候只需要在MyBatis核心配置文档mybatis-config.xml中,配置一下就可以自动进行转换了

    <settings>
        <!--开启下划线转驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
  6. 开启日志

    开启事务能够在控制台打印程序执行的详细信息,帮助我们改错

    在下划线转驼峰命名的配置下方进行配置

    <settings>
        <!--开启下划线转驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
  7. 使用unit测试工具进行测试

    往表中添加博客记录,以便后面进行观察

    package org.westos.mapper;
    
    import org.junit.Test;
    import org.westos.pojo.Blog;
    import org.westos.utils.IDUtils;
    import org.westos.utils.MyBatisUtil;
    import java.util.Date;
    
    
    public class BlogMapperTest {
    
        @Test
        public void testAddBlog() {
            //传递参数,默认开启事务提交
            BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class);
            Blog blog;
            //循环给表中添加数据
            for (int i = 0; i < 10; i++) {
                blog = new Blog();
                blog.setId(IDUtils.getId());
                blog.setTitle("文章" + i);
                blog.setAuthor("北风");
                blog.setCreateTime(new Date());
                blog.setViews(i * 1000);
                mapper.addBlog(blog);
            }
        }
    }
    
  8. IDUtils工具类

    工具类,创建随机数,作为文章的id

    package org.westos.utils;
    
    import java.util.UUID;
    
    public class IDUtils {
        public static String getId() {
            return UUID.randomUUID().toString().replaceAll("-", "");
        }
    }
    

2、if标签

常用于where语句、update语句、insert语句中,通过判断if后表达式的取值决定是否使用if标签中的子句。

当判断条件为真的时候,添加if标签中的子句,当判断条件为假的时候,什么都不加

if是与的关系(and)

java代码

//BlogMapper接口新增方法
//查询博客
List<Blog> getBlogByIf(Map map);

//BlogMapperTest中新增测试方法
@Test
public void testGetBlogByIf() {
    BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class);
    //创建Map集合,用的参数从Map集合中拿
    Map<String, String> map = new HashMap<String, String>();
    map.put("title","wenzhang1");
    map.put("author","beifeng");

    List<Blog> blogByIf = mapper.getBlogByIf(map);
    for (Blog blog : blogByIf) {
        System.out.println(blog);
    }
}

xml配置

<!--根据if标签后的表达式的值来决定SQL语句-->
<select id="getBlogByIf" parameterType="Map" resultType="Blog">
    select * from mybatis.blog where
    <!--通过判断if后表达式的值,决定是否要添加if标签中的子句-->
    <if test="title!=null">
        title=#{title}
    </if>
    <if test="author!=null">
        and  author =#{author}
    </if>
</select>

3、choose标签(when,otherwise)

类似于Java中的switch语句,当匹配到成立的when标签后的条件时,就执行这个when标签后的SQL子句,choose标签结束。当所有的when标签都不成立时,执行otherwise标签中的SQL子句

choose是或的关系(or)

java代码

//BlogMapper新增接口
List<Blog> queryBlogByChoose(Map map);

//测试类新增测试方法
@Test
public void testQueryBlogByChoose() {
    BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
    Map<String, String> map = new HashMap<String, String>();
    map.put("title", "wenzhang1");
    map.put("author", "beifeng");

    List<Blog> blogByIf = mapper.getBlogByIf(map);
    for (Blog blog : blogByIf) {
        System.out.println(blog);
    }
}

xml配置

<!--使用choose标签-->
<select id="queryBlogByChoose" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <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>

4、trim标签(where,set)

where:当where标签中有返回值的话,它就插入一个where子句,如果没有,如果标签返回的内容是以 AND 或 OR 或 “,” 开头结尾的,则它会删除掉

java代码

//接口
List<Blog> selectBlogByWhere(Map map);

//测试方法
@Test
public void testSelectBlogByWhere() {
    BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
    Map<String, String> map = new HashMap<String, String>();
    map.put("title", "wenzhang1");
    map.put("author", "beifeng");

    List<Blog> blogByIf = mapper.selectBlogByWhere(map);
    for (Blog blog : blogByIf) {
        System.out.println(blog);
    }
}

xml配置

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

set:当在 update 语句中使用 if 标签时,如果最后的 if 没有执行,则或导致逗号多余错误。使用 set 标签可以将动态的配置 set关键字,并删除追加到条件末尾的任何不相关的逗号

java代码

//接口
int updateBlogBySete(Map map);

//测试方法
@Test
public void testUpdateBlogBySete() {
    //开启事务提交
    BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class);
    Map<String, String> map = new HashMap<String, String>();

    //给Map中填充数据
    map.put("title", "123123123");
    map.put("author", "11111111");
    map.put("id", "8bc79ab97f6f4887a2e61ae7d6512453");
    //打印受影响行数
    int i = mapper.updateBlogBySete(map);
    System.out.println(i);
}

xml配置

<update id="updateBlogBySete" parameterType="map">
    update mybatis.blog
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>

5、foreach标签

foreach主要用于构建in条件,也可在SQl中对集合进行迭代。批量增删等操作

foreach标签的属性

  1. collection

    表明存储的参数类型,对应的值分别为:list(List)、array(数组)、map(map集合)

  2. item

    在迭代的过程中元素的别名

  3. index

    在迭代的过程中,迭代的位置

  4. open

    前括号

  5. close

    后括号

  6. separator

    分隔符,表示迭代的时候以什么符号分隔元素

java代码

//接口
List<Blog> getBlogByForeach(Map map);

//测试方法
@Test
public void testGetBlogByForeach() {
    BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
    Map<String, List> map = new HashMap<String, List>();
    List<String> ids = new ArrayList<String>();
    ids.add("8bc79ab97f6f4887a2e61ae7d6512453");
    ids.add("d38e8e24768249eb8c0a671e64e5991f");
    ids.add("35e3643a0ab14b18b018b72146d1f0d4");

    map.put("ids", ids);
    List<Blog> blogByIf = mapper.getBlogByIf(map);
    for (Blog blog : blogByIf) {
        System.out.println(blog);
    }
}

xml配置

<select id="getBlogByForeach" parameterType="map" resultType="blog">
    select * from user where
    <!--得到map集合里的键值对,值为List集合,然后遍历得到值,使用or链接起来-->
    <foreach item="id" collection="ids"
             open="(" separator="or" close=")">
        #{id}
    </foreach>
</select>

6、SQL片段

将一些SQL语句公用的部分抽取出来,实现代码复

  1. 使用SQL标签抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    
  2. 将前面的if标签引用进来,使用include标签

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值