Mybatis系列九之动态sql

动态sql

动态sql:根据不同的条件生成不同的SQL语句

1. 搭建环境

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
	
	
insert into blog values("001","java","小明","2021-1-11",45);
insert into blog values("002","python","小亮","2021-2-11",100);	
insert into blog values("003","c++","小红","2021-3-11",99);	
insert into blog values("004","c","小张","2021-1-18",46);	
insert into blog values("005","php","小辉","2021-1-21",87);	
insert into blog values("006","js","小刘","2021-7-21",68);

2 实体类

随机生成随机的id编号

import java.util.UUID;

@SuppressWarnings("all")
public class IDutils {

    public static String getId(){
        return UUID.randomUUID().toString().replace("-","");   }

}

测试接口

import com.xgh.pojo.Blog;

import java.util.List;

public interface BlogMapper {
    //测试添加数据
    int addBlog(Blog blog);

    //测试查询所有方法
    List<Blog> findAll();
}

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="com.xgh.dao.BlogMapper">
    <insert id="addBlog" parameterType="Blog">
        insert into blog (id, title, author, create_time, views) values
        (#{id}, #{title}, #{author}, #{create_time}, #{views});
    </insert>

    <select id="findAll" resultType="Blog">
        select * from blog;
    </select>
</mapper>

3 分类

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

格式:

<if test="判断语句">

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

解析此段:如果map集合为空,则查出来的结果为所有,select * from blog where 1 = 1

如果map集合中 title含有值 则where条件中为此条件

3.2 choose (when, otherwise)

相当于java中的switch case语句

<select id="findBlogChoose" resultType="Blog" parameterType="map">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                id = #{id}
            </otherwise>
        </choose>
    </where>
</select>
3.3 trim (where, set)

where 解决不能匹配的问题

匹配的只是第二个条件又会怎样?这条 SQL 会是这样:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

正确格式

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

set设置更新条件

用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列

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>

trm是where和set的父标签

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

来看看与 set 元素等价的自定义 trim 元素吧:

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

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

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

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

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。

    <!--动态sqlForeach遍历-->
<!-- 拼接成的动态sql语句 SELECT * FROM blog WHERE ID in ( ? ) -->
    <select id="findBlogForeach" resultType="Blog" parameterType="map">
        SELECT *
        FROM blog
        WHERE ID in
        <foreach item="id" collection="ids"
                 open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

测试类

@Test
    public void findBlogForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();

        ArrayList<String> ids = new ArrayList<String>();
        ids.add("001");
        ids.add("002");

        map.put("ids",ids);

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

    }

4 SQL片段

有些时候我们有一些公共部分

  1. 使用sql便签抽取公共部分
  2. 在使用的地方使用include标签
<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="Blog">
    select * from mybatis.blog
    <where>
        <include refid="if-title-author"/>
    </where>
</select>

注意:

  • 最好基于单表
  • sql里不要存在where标签
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值