• 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 对象时,没有设置的新的属性值,就保持原来的值,设置了新的值,才更

    新.

    解决方案分析

    1. 从上面的需求我们可以看出,有时我们在生成 sql 语句时,在同一个方法中,还要根据
    不同的情况生成不同的 sql 语句

    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-案例演示

    3.1 if 标签应用实例

    需求:请查询 age 大于 10 的所有妖怪,如果程序员输入的 age 不大于 0, 则输出所有
    的妖怪
    1. //根据age查询结果
    2. public List findMonsterByAge(@Param(value = "age") Integer age);
    1. <select id="findMonsterByAge" resultType="Monster" parameterType="Integer">
    2. SELECT * FROM `monster` WHERE 1 = 1
    3. <if test="age >= 0">
    4. AND age > #{age}
    5. if>
    6. select>
    1. public void findMonsterByAge() {
    2. List monsters =
    3. monsterMapper.findMonsterByAge(10);
    4. for (Monster monster : monsters) {
    5. System.out.println("monster--" + monster);
    6. }
    7. if (sqlSession != null) {
    8. sqlSession.close();
    9. }
    10. System.out.println("操作成功~");
    11. }

    3.2where 标签应用实例

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

    ● where 标签应用实例
    需求:查询 id 大于 20 的,并且名字是 " 牛魔王 " 的所有妖怪 , 注意,如果名字为空,
    或者输入的 id 小于 0, 则不拼接 sql 语句 ( 梳理:如果名字为空 , 就不带名字条件 ,
    如果输入的 id 小于 0, 就不带 id 的条件 )
    1. //根据id和名字来查询结果
    2. public List findMonsterByIdAndName(Monster monster);
    1. <select id="findMonsterByIdAndName" parameterType="Monster" resultType="Monster">
    2. SELECT * FROM `monster`
    3. <where>
    4. <if test="id >= 0">
    5. AND `id` > #{id}
    6. if>
    7. <if test="name != null and name != ''">
    8. AND `name` = #{name}
    9. if>
    10. where>
    11. select>
    1. public void findMonsterByIdAndName() {
    2. Monster monster = new Monster();
    3. monster.setId(1);
    4. monster.setName("牛魔王-100");
    5. List monsters = monsterMapper.findMonsterByIdAndName(monster);
    6. for (Monster m : monsters) {
    7. System.out.println("m--" + m);
    8. }
    9. if (sqlSession != null) {
    10. sqlSession.close();
    11. }
    12. System.out.println("操作成功~");
    13. }

    3.3choose/when/otherwise 应用实例

    有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句(choose=switch;when=case;otherwise=default

    需求:如果给的 name 不为空,就按名字查询妖怪,如果指定的 id>0 ,就按 id 来查询妖
    怪, 要求使用 choose/when/otherwise 标签实现 , 传入参数要求使用 Map
    1. //测试choose标签的使用
    2. public List findMonsterByIdOrName_choose(Map map);
    1. <select id="findMonsterByIdOrName_choose" parameterType="map" resultType="Monster">
    2. SELECT * FROM `monster`
    3. <choose>
    4. <when test="name != null and name != ''">
    5. WHERE `name` = #{name}
    6. when>
    7. <when test="id > 0">
    8. WHERE `id` > #{id}
    9. when>
    10. <otherwise>
    11. WHERE `salary` > 100
    12. otherwise>
    13. choose>
    14. select>
    1. public void findMonsterByIdOrName_choose() {
    2. Map map = new HashMap<>();
    3. //map.put("name", "牛魔王-100");
    4. map.put("id", -1);
    5. List monsters = monsterMapper.findMonsterByIdOrName_choose(map);
    6. for (Monster monster : monsters) {
    7. System.out.println("monster--" + monster);
    8. }
    9. if (sqlSession != null) {
    10. sqlSession.close();
    11. }
    12. System.out.println("操作成功~");
    13. }

    3.4.forEach 标签应用实例

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

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

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

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

    1. //测试foreach的标签使用
    2. public List findMonsterById_forEach(Map map);
    1. <select id="findMonsterById_forEach" parameterType="map" resultType="Monster">
    2. SELECT * FROM `monster`
    3. <if test="ids != null and ids !=''">
    4. <where>
    5. id IN
    6. <foreach collection="ids" item="id" open="(" separator="," close=")">
    7. #{id}
    8. foreach>
    9. where>
    10. if>
    11. select>
    1. public void findMonsterById_forEach() {
    2. Map map = new HashMap<>();
    3. map.put("ids", Arrays.asList(10, 12, 14));
    4. List monsters =
    5. monsterMapper.findMonsterById_forEach(map);
    6. for (Monster monster : monsters) {
    7. System.out.println("monster--" + monster);
    8. }
    9. if (sqlSession != null) {
    10. sqlSession.close();
    11. }
    12. System.out.println("操作成功~");
    13. }

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

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

    where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能

    理解:就是trim prefix="WHERE" prefixOverrides="and|or|hong" 若子句的开头为 “AND” 或 “OR 或"hong" , 就去除,而这个where就是带上where的功能

    要求:按名字和年龄查询妖怪,如果 sql 语句有 and | or 就替换成 where
    1. //trim标签的使用
    2. public List findMonsterByName_Trim(Map map);
    1. <select id="findMonsterByName_Trim" parameterType="map" resultType="Monster">
    2. SELECT * FROM `monster`
    3. <trim prefix="WHERE" prefixOverrides="and|or|hong">
    4. <if test="name != null and name != ''">
    5. AND `name` = #{name}
    6. if>
    7. <if test="age != null and age != ''">
    8. AND `age` > #{age}
    9. if>
    10. trim>
    11. select>

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

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

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

    1. //测试Set标签
    2. public void updateMonster_set(Map map);
    1. <update id="updateMonster_set" parameterType="map">
    2. UPDATE `monster`
    3. <set>
    4. <if test="age != null and age != ''">
    5. `age` = #{age} ,
    6. if>
    7. <if test="email != null and email != ''">
    8. `email` = #{email} ,
    9. if>
    10. <if test="name != null and name != ''">
    11. `name` = #{name} ,
    12. if>
    13. <if test="birthday != null and birthday != ''">
    14. `birthday` = #{birthday} ,
    15. if>
    16. <if test="salary != null and salary != ''">
    17. `salary` = #{salary} ,
    18. if>
    19. <if test="gender != null and gender != ''">
    20. `gender` = #{gender} ,
    21. if>
    22. set>
    23. WHERE id = #{id}
    24. update>
    1. public void updateMonster_set() {
    2. Map map = new HashMap<>();
    3. map.put("id", 3);
    4. map.put("name", "牛魔王5-100");
    5. monsterMapper.updateMonster_set(map);
    6. //修改需要有commit
    7. if (sqlSession != null) {
    8. sqlSession.commit();
    9. sqlSession.close();
    10. }
    11. System.out.println("操作成功~");
    12. }

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

  • 相关阅读:
    volatile修饰数组
    复制文件描述符(dup、dup2函数) 和 文件共享
    【Vue】Provide,Inject,模版 Ref 的用法
    基于MATLAB的人民币识别系统
    TikTok直播赚钱教程
    AWS DAS认证考点整理(Athena&Glue篇)
    Promise——promise是什么?为什么要用promise?
    YOLOv8更换骨干网络HorNet:递归门控卷积的高效高阶空间交互——涨点神器!
    大数据之Hive(三)
    CentOS8 安装Cloc代码统计工具
  • 原文地址:https://blog.csdn.net/weixin_54107527/article/details/127807304