mybatis之动态SQL (八)

一 动态SQL

什么是动态sql?

动态SQL就是说根据不同的条件,生成不同的sql语句!!!!

二 if标签

<if test="title!=null" >
            	title=#{title}
            </if>

这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果(细心的读者可能会发现,“title” 的参数值需要包含查找掩码或通配符字符)。

对比:

1 原先的Blog.xml文件当中的语句

<select id="queryBlogByTitleAndAuthor" resultType="Blog" parameterType="map">
        select * from blog where title=#{title}and author=#{author}

可能会出现的状况:

1.1  设置参数不完整

@Test
    //原来的通过title和author查询blog  如果测试的时候参数不设置或者错误就会报错
    public void testqueryBlogByTitleAndAuthor(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第一本书");
        //map.put("author","莫言");
        List<Blog> blogs = mapper.queryBlogByTitleAndAuthor(map);
        for (Blog blogs2 : blogs) {
            System.out.println(blogs2);
        }
        sqlSession.close();
    }

 1.2参数设置的与上去了语句不匹配 参数设置title和view字段而sql语句是title和author字段

@Test
    //原来的通过title和author查询blog  如果测试的时候参数不设置或者错误就会报错
    public void testqueryBlogByTitleAndAuthor(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第一本书");
        map.put("view",9999);
        List<Blog> blogs = mapper.queryBlogByTitleAndAuthor(map);
        for (Blog blogs2 : blogs) {
            System.out.println(blogs2);
        }
        sqlSession.close();
    }

 都会显示没有查询结果

1.3只有与sql语句的条件完成匹配才可以搜索出来

@Test
    //原来的通过title和author查询blog  如果测试的时候参数不设置或者错误就会报错
    public void testqueryBlogByTitleAndAuthor(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第一本书");
        map.put("author","莫言");
        List<Blog> blogs = mapper.queryBlogByTitleAndAuthor(map);
        for (Blog blogs2 : blogs) {
            System.out.println(blogs2);
        }
        sqlSession.close();
    }


 2 利用动态sql后(利用动态sql就不会)

BlogMapper.xml文件代码:

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

2.1设置完整

@Test
    //通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
    public void testqueryBlogByIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第二本书");
        map.put("author","莫言");

        List<Blog> blogs = mapper.queryBlogByIF(map);
        for (Blog blogs3 : blogs) {
            System.out.println(blogs3);
        }
        sqlSession.close();
    }

2.2.测试的时候设置参数不完整也可以按照第一个的查询

这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title}

@Test
//通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
public void testqueryBlogByIF(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    map.put("title","莫言第二本书");
    //map.put("author","莫言");

    List<Blog> blogs = mapper.queryBlogByIF(map);
    for (Blog blogs3 : blogs) {
        System.out.println(blogs3);
    }
    sqlSession.close();
}

2.3如果设置第二个条件也会报错 因为sql语句错误了 需要使用trim当中的<where>标签

这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title},但是如果title为空呢?那么查询语句为 select * from user where and author=#{author},这是错误的 SQL 语句,如何解决呢?请看下面的 where 语句!

@Test
    //通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
    public void testqueryBlogByIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第二本书");
        map.put("author","莫言");

        List<Blog> blogs = mapper.queryBlogByIF(map);
        for (Blog blogs3 : blogs) {
            System.out.println(blogs3);
        }
        sqlSession.close();
    }

上图当中SQL语句错误了。

使用了<where>标签

代码:

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

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

2.4 测试的时候设置的参数类型与sql语句不一样 sql当中是title和author字段而测试时是author和views字段

@Test
    //通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
    public void testqueryBlogByIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第二本书");
        map.put("author","莫言");
        map.put("view",9999);

        List<Blog> blogs = mapper.queryBlogByIF(map);
        for (Blog blogs3 : blogs) {
            System.out.println(blogs3);
        }
        sqlSession.close();
    }

 2.5 如果测试的时候设置的参数都不是sql的呢? 全部显示

@Test
    //通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
    public void testqueryBlogByIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第二本书");
        //map.put("author","莫言");
        map.put("view",9999);

        List<Blog> blogs = mapper.queryBlogByIF(map);
        for (Blog blogs3 : blogs) {
            System.out.println(blogs3);
        }
        sqlSession.close();
    }

那就是全部显示了

2.7如果什么都不设置呢?全部显示

@Test
    //通过动态sql当中if标签实现 如果测试的时候参数不设置就全部显示
    public void testqueryBlogByIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第二本书");
        //map.put("author","莫言");
        //map.put("view",9999);

        List<Blog> blogs = mapper.queryBlogByIF(map);
        for (Blog blogs3 : blogs) {
            System.out.println(blogs3);
        }
        sqlSession.close();
    }

三 choose标签

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

BlogMapper.xml文件代码:

<select id="queryBlogByChoose" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    title=#{title}
                </when>
                <when test="views==9999">
                    and views=#{views}
                </when>
                <otherwise>
                    and author=#{author}
                </otherwise>
            </choose>
        </where>
    </select>

1 按照第一个case:设置title

a 测试类单独设置了title的

@Test
    public void testqueryBlogByChoose(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第一本书");
        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blogs4 : blogs) {
            System.out.println(blogs4);
        }

        sqlSession.close();
    }

 b 测试类还设置了别的参数

@Test
    public void testqueryBlogByChoose(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","莫言第一本书");
        map.put("views",1000);
        //map.put("author","史铁生");
        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blogs4 : blogs) {
            System.out.println(blogs4);
        }

        sqlSession.close();
    }

2 按照第二个 views=9999

@Test
    public void testqueryBlogByChoose(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("views",9999);
        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blogs4 : blogs) {
            System.out.println(blogs4);
        }

        sqlSession.close();
    }

 

 在views=9999的基础上额外加上author=“史铁生”

 @Test
    public void testqueryBlogByChoose(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第一本书");
        map.put("views",9999);
        map.put("author","史铁生");
        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blogs4 : blogs) {
            System.out.println(blogs4);
        }

        sqlSession.close();
    }

 3 前面条件都不满足

@Test
    public void testqueryBlogByChoose(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //map.put("title","莫言第一本书");
        map.put("views",1000);
        map.put("author","史铁生");
        List<Blog> blogs = mapper.queryBlogByChoose(map);
        for (Blog blogs4 : blogs) {
            System.out.println(blogs4);
        }

        sqlSession.close();
    }

四 trim标签

4.1where标签

where标签如上诉所示 在if标签当中的例子

4.2 set标签

同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?

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

注意逗号

1 修改作者和标题 通过id 测试的时候相应的参数全部输入

 @Test
    //通过动态SQL当中的set标签 会像where一样 set智能的省略 ”,“ 和前置set标签
    public void testUpdateBySet(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();

        map.put("title","settitle为动态sql的莫言第一本书");
        map.put("author","setauthor为动态sql的莫言2号");
        map.put("id","1");
        mapper.updateBlogBySet(map);
        System.out.println();
        sqlSession.close();
    }

注意sql语句

 注意事物的提交 否则数据库单中不会修改

2注释第一个条件

  @Test
    //通过动态SQL当中的set标签 会像where一样 set智能的省略 ”,“ 和前置set标签
    public void testUpdateBySet(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();

        //map.put("title","settitle为动态sql的莫言第一本书");
        map.put("author","setauthor为动态sql的莫言2号");
        map.put("id","1");
        mapper.updateBlogBySet(map);
        sqlSession.commit();
        sqlSession.close();
    }

3 注释第二个条件 我们可以看到 条件一后面的,被智能的省略了 只是由于set标签的作用

 @Test
    //通过动态SQL当中的set标签 会像where一样 set智能的省略 ”,“ 和前置set标签
    public void testUpdateBySet(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();

        map.put("title","settitle为动态sql的莫言第一本书");
        //map.put("author","setauthor为动态sql的莫言2号");
        map.put("id","1");
        mapper.updateBlogBySet(map);
        sqlSession.commit();
        sqlSession.close();
    }

五 foreach标签

遍历

需求:我想要查询id为1-3的记录 不采用分页 可以使用foreach标签

BlogMapper.xml文件

代码:

 <!--
       collection:指定输入对象中的集合属性
       item:每次遍历生成的对象
       open:开始遍历时的拼接字符串
       close:结束时拼接的字符串
       separator:遍历对象之间需要拼接的字符串
       select * from blog where 1=1 and (id=1 or id=2 or id=3)
     -->
 <select id="queryBlogByForEach" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <foreach collection="ids" open="(" separator="or" close=")" item="id">
                id=#{id}
            </foreach>
        </where>
    </select>

测试类代码

@Test
public void testqueryBlogByForEach(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    ArrayList ids = new ArrayList();
    ids.add("1");
    ids.add("2");
    ids.add("3");
    map.put("ids",ids);
    List<Blog> blogs = mapper.queryBlogByForEach(map);
    for (Blog blogs6 : blogs) {
        System.out.println(blogs6);
    }
    sqlSession.close();
}

6 sql片段

sql片段 利用sql标签

需求:

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

BlogMapper.xml文件的代码

提取sql片段

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

    </sql>

引用sql片段

<select id="queryBlogByIF2" parameterType="map" resultType="Blog" >
        select * from blog
        <where>
            <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->

            <include refid="if-title-author" >
                <!-- 在这里还可以引用其他的 sql 片段 -->
            </include>
        </where>
    </select>

测试类代码

@Test
//优化 使用sql片段 减少代码的重用性
public void testqueryBlogByIF2(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    map.put("title","莫言第二本书");
    map.put("author","莫言");
    //map.put("view",9999);

    List<Blog> blogs = mapper.queryBlogByIF2(map);
    for (Blog blogs3 : blogs) {
        System.out.println(blogs3);
    }
    sqlSession.close();
}

注意:

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

②、在 sql 片段中不要包括 where

小结:其实动态 sql 语句的编写往往就是一个拼接的问题,

为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。

多在实践中使用才是熟练掌握它的技巧。


强调一下动态SQL 功能点

1 if标签

不同的参数实现动态效果 在sql当中判断

比如说我想查询书名是《狂神这么厉害》 那我就需要一个方法是通过书名 再给个参数来查询记录

我想查询作者是“狂神说” 那么我又需要一个方法就是:通过作者 再给个作者的参数 来查询记录

就会有很多个方法 代码的累赘

=====》》》如果使用了动态sql

就需要这么多个方法 只需要一个方法 且利用sql语句的动态性 改变参数就可以实现上述效果。

2 chooes标签

他其实就好比Java当中的switch语句 并且他不会像原始的方法那样必须参数对参数全部都要一样才可以 利用动态sql可以动态的改变 根据不同的条件得到不同的结果集。

3foreach标签

遍历 比如说我想要某几条数据 需要给出索引下标就可以得到 不需要用分页的

4 trim标签

trim标签包含<where>和<set>这两个子标签

where的作用是前置where和智能的省略and和or关键字

set的作用是前置set关键字和智能的省略逗号”,“

动态SQL的关键就是

  1. 根据不同的条件得到不同的结果集。

  2. 动态sql的本身其实还是sql语句,只是我们在sql的层面上,去执行了一个逻辑代码!

  3. 动态SQL是拼接sql语句 我们需要保证他sql语句的正确性 。=======》》》》 因此我们需要先提前写好sql语句是否能够正常运行再去再mybatis当中的动态sql当中去修改

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MyBatis是一个流行的Java持久层框架,它允许开发者在运行时构建动态SQL查询,从而提高了代码的灵活性和适应性。MyBatis通过结合XML映射文件和注解,实现了动态SQL的执行。以下是MyBatis动态SQL的主要实现方式: 1. XML映射文件(Mapper XML):在MyBatis中,`<select>`, `<update>`, `<delete>`等标签可以包含参数占位符,如`#{id}`, `#{name}`,这些占位符会在运行时被实际的值替换,形成动态SQL语句。 ```xml <select id="getUser" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id} </select> ``` 2. 参数化查询(Parametrized queries):MyBatis支持使用预编译语句,将参数与SQL语句分离,这样可以防止SQL注入攻击。 3. 显式对象(Parameter Objects):如果动态SQL非常复杂,可以创建一个Java对象作为参数传递给查询,其中包含了多个属性,MyBatis会自动将对象的属性转换为SQL中的列名。 ```java Map<String, Object> params = new HashMap<>(); params.put("startDate", startDate); params.put("endDate", endDate); List<User> users = sqlSession.selectList("getUsers", params); ``` 4. 动态SQL标签:MyBatis提供了`<if>`, `<choose>`, `<when>`, `<otherwise>`等标签,用于根据条件动态生成SQL,实现基于条件的分支查询。 ```xml <select id="getUser" parameterType="map" resultType="User"> <if test="id != null"> SELECT * FROM users WHERE id = #{id} </if> <if test="name != null"> AND name LIKE '%' + #{name} + '%' </if> </select> ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值