【SSM框架】Mybatis动态SQL

目标

  1. 了解mybatis的动态SQL

  2. 了解并学会使用IF-WHERE 动态sql语句

  3. 了解并学会使用SET 动态sql语句

  4. 了解并学会使用SQL片段 动态sql语句

  5. 了解并学会使用Foreach 动态sql语句

一、介绍

什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.

官网描述:
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

我们之前写的 SQL 语句都比较简单,如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。

那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。

二.、环境准备

1. 创建数据库,新建一个blog表

DROP TABLE IF EXISTS `blog`;
CREATE TABLE `blog`  (
  `id` int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT COMMENT '博客id',
  `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客标题',
  `author` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '博客作者',
  `create_time` datetime(0) NOT NULL COMMENT '创建时间',
  `views` int(30) NOT NULL COMMENT '浏览量',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

2. 实体类编写

@Data
public class Blog {
    
    
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

3. 编写Mapper接口和xml文件

    /**
     *功能描述: 新增一篇博客
     * @param blog 博客试题
     * @return int
    */
    int addBlog(Blog blog);
<?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.shida.mapper.BlogMapper">
    
</mapper>

4. 插入初始数据

编写接口

    /**
     *功能描述: 新增一篇博客
     * @param blog 博客试题
     * @return int
    */
    int addBlog(Blog blog);

编写xml

 <!--注意配置别名-->
    <insert id="addBlog" parameterType="blog">
      insert into blog (id, title, author, create_time, views)
      values (#{id},#{title},#{author},#{createTime},#{views});
    </insert>

初始化博客

@Test
    public void addInitBlog(){
    
    
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Blog blog = new Blog();
        blog.setTitle("Mybatis");
        blog.setAuthor("焦前进");
        blog.setCreateTime(new Date());
        blog.setViews(9999);

        mapper.addBlog(blog);

        blog.setTitle("Spring");
        mapper.addBlog(blog);

        blog.setTitle("SpringMVC");
        mapper.addBlog(blog);

        session.close();
    }

三、IF-WHERE语句

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

1. 编写参数实体类

@Data
public class BlogDTO {
    
    
    private String title;
    private String author;
}

2.编写接口类

 /**
     *功能描述: 根据条件查询
     * @param blogDTO 参数
     * @return java.util.List<com.shida.entity.Blog>

    */
    List<Blog> queryBlogIf(BlogDTO blogDTO);

3.编写xml

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

4. 测试

    @Test
    public void testQueryBlogIf(){
    
    
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        BlogDTO blogDTO = new BlogDTO();
        blogDTO.setTitle("Mybatis");
        blogDTO.setAuthor("焦前进");
        List<Blog> blogs = mapper.queryBlogIf(blogDTO);

        System.out.println(blogs);

        session.close();
    }

测试结果

1. 如果author为空,只根据title去查

img

2. 如果Title为空,只根据auther去查

img

“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

四、Set语句

需求:根据博客ID修改博客,如果博客作者为空,则修改博客标题,如果博客标题为空,则修改博客作者

1. 编写修改接口

/**
     *功能描述: 修改博客
     * @param blogDTO 修改信息
     * @return int
    */
    int updateBlog(BlogDTO blogDTO);

2. 编写xml

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

3. 测试

    @Test
    public void testUpdateBlog() {
    
    
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        BlogDTO blogDTO = new BlogDTO();
        blogDTO.setTitle("Mybatis真难啊");
//        blogDTO.setAuthor("焦前进");
        blogDTO.setId(1);

        mapper.updateBlog(blogDTO);
        session.close();
    }

1. auther为空,修改title

img

2. title为空,修改auther

img

五、SQL片段

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

声明一个SQL片段

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

引用SQL片段

<!--注意set是用的逗号隔开-->
<update id="updateBlog" parameterType="blogDTO">
    update blog
    <set>
        <include refid="if-title-author"></include>
         <!-- 在这里还可以引用其他的 sql 片段 -->
    </set>
    where id = #{id};
</update>

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

②在 sql 片段中不要包括 where

六、Foreach语句

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

1. 编写接口

/**
     *功能描述: 查询多个id的博客
     * @param list 参数集合
     * @return java.util.List<com.shida.entity.Blog>
    */
List<Blog> queryBlogForeach(List<Integer> list);

2. 编写xml

<select id="queryBlogForeach" parameterType="list" 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="list"  item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>

3. 测试

@Test
    public void testQueryBlogForeach(){
    
    
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

       List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);

        List<Blog> blogs = mapper.queryBlogForeach(list);

        System.out.println(blogs);

        session.close();
    }

七、总结

其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。多在实践中使用才是熟练掌握它的技巧。

上一篇:

【SSM框架】Mybatis的基本使用
https://blog.csdn.net/qq_45696377/article/details/122160827?spm=1001.2014.3001.5502

下一篇:

【SSM框架】Mybatis逆向生成

猜你喜欢

转载自blog.csdn.net/qq_45696377/article/details/122268668