MyBatis中动态 SQL 语句-更复杂的查询业务需求

1.为什么需要动态 SQL

2.动态 SQL-基本介绍

3.动态 SQL-案例演示

3.1 if 标签应用实例

3.2where 标签应用实例

3.3choose/when/otherwise 应用实例

3.4.forEach 标签应用实例

3.5.trim 标签应用实例【使用较少】

3.6.set 标签应用实例[重点]

1.为什么需要动态 SQL

1 、动态 SQL 是 MyBatis 的强大特性之一

2 、使用 JDBC 或其它类似的框架,根据不同条件拼接 SQL 语句非常麻烦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号等

3 、 SQL 映射语句中的强大的动态 SQL 语言 , 可以很好的解决这个问题 .

2.动态 SQL- 基本介绍

基本介绍

  1. 在一个实际的项目中, sql 语句往往是比较复杂的

  2. 为了满足更加复杂的业务需求, MyBatis 的设计者,提供了动态生成 SQL 的功能。

动态 SQL 必要性

  1. 比如我们查询 Monster 时,如果程序员输入的 age 不大于 0, 我们的 sql 语句就不带 age 。

  2. 更新 Monster 对象时,没有设置的新的属性值,就保持原来的值,设置了新的值,才更

2.解决方案: MyBatis 提供的动态SQL 机制

动态 SQL 常用标签

动态 SQL 提供了如下几种常用的标签,类似我们 Java 的控制语句:

  1. if [ 判断 ]

  2. where [ 拼接 where 子句 ]

  3. choose/when/otherwise [ 类似 java 的 switch 语句 , 注意是单分支 ]

  4. foreach [ 类似 in ]

  5. trim [ 替换关键字 / 定制元素的功能 ]

  6. set [ 在 update 的 set 中,可以保证进入 set 标签的属性被修改,而没有进入 set 的,保

持原来的值 ]

3.动态 SQL- 案例演示

● 需求:请查询 age 大于 10 的所有妖怪,如果程序员输入的 age 不大于 0, 则输出所有

的妖怪

//根据age查询结果
    public List findMonsterByAge(@Param(value = "age") Integer age);

        SELECT * FROM monster WHERE 1 = 1

            AND age > #{age}

    public void findMonsterByAge() {
        List monsters =
                monsterMapper.findMonsterByAge(10);
        for (Monster monster : monsters) {
            System.out.println("monster--" + monster);
        }
        if (sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作成功~");
    }

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

● where 标签应用实例

需求:查询 id 大于 20 的,并且名字是 ” 牛魔王 ” 的所有妖怪 , 注意,如果名字为空,

或者输入的 id 小于 0, 则不拼接 sql 语句 ( 梳理:如果名字为空 , 就不带名字条件 ,

如果输入的 id 小于 0, 就不带 id 的条件 )

● 需求:如果给的 name 不为空,就按名字查询妖怪,如果指定的 id>0 ,就按 id 来查询妖

怪, 要求使用 choose/when/otherwise 标签实现 , 传入参数要求使用 Map

    //测试choose标签的使用
    public List findMonsterByIdOrName_choose(Map map);

        SELECT * FROM monster

                WHERE name = #{name}

                WHERE id > #{id}

                WHERE salary > 100

    public void findMonsterByIdOrName_choose() {

        Map map = new HashMap<>();
        //map.put("name", "牛魔王-100");
        map.put("id", -1);

        List monsters = monsterMapper.findMonsterByIdOrName_choose(map);
        for (Monster monster : monsters) {
            System.out.println("monster--" + monster);
        }

        if (sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作成功~");
    }

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

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 :你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach 。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

●需求:查询monster_id 为20, 22, 34 的妖怪

    //测试foreach的标签使用
    public List findMonsterById_forEach(Map map);

        SELECT * FROM monster

                id IN

                    #{id}

    public void findMonsterById_forEach() {

        Map map = new HashMap<>();
        map.put("ids", Arrays.asList(10, 12, 14));

        List monsters =
                monsterMapper.findMonsterById_forEach(map);

        for (Monster monster : monsters) {
            System.out.println("monster--" + monster);
        }

        if (sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作成功~");

    }

● trim 可以替换一些关键字 .

要求:按名字和年龄查询妖怪,如果 sql 语句有 and | or 就替换成 where

    //trim标签的使用
    public List findMonsterByName_Trim(Map map);

        SELECT * FROM monster

                AND name = #{name}

                AND age > #{age}

set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。

●需求:请对指定id 的妖怪进行 修改,如果没有设置新的属性,则保持原来的值

    //测试Set标签
    public void updateMonster_set(Map map);

        UPDATE monster

                age = #{age} ,

                email = #{email} ,

                name = #{name} ,

                birthday = #{birthday} ,

                salary = #{salary} ,

                gender = #{gender} ,

        WHERE id = #{id}

    public void updateMonster_set() {
        Map map = new HashMap<>();
        map.put("id", 3);
        map.put("name", "牛魔王5-100");

        monsterMapper.updateMonster_set(map);

        //修改需要有commit
        if (sqlSession != null) {
            sqlSession.commit();
            sqlSession.close();
        }
        System.out.println("操作成功~");
    }

像这个例子我们就可以看出来set是利用if的判断,如果我们在测试文件中没有改变,那么就是空,这个时候就会还是原来的值,相反当我们进行改变的时候,不为空,那么相应的字段的值就会发生改变——>这个例子就是把name字段进行了改变,其他的字段没有发生变化

Original: https://blog.csdn.net/weixin_54107527/article/details/127807304
Author: 海绵hong
Title: MyBatis中动态 SQL 语句-更复杂的查询业务需求

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/653617/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球