• 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字段进行了改变,其他的字段没有发生变化

  • 相关阅读:
    monaco-editor插件自定义编辑器内容颜色
    python_data_analysis_and_mining_action-master-7
    Leetcode数据库系列题解合集(持续更新)
    手把手教你Nginx常用模块详解之ngx_http_upstream_module(六)
    十大经典排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序)
    Femas:云原生多运行时微服务框架
    css的三大特性
    Redis根据中心点坐标和半径筛选符合的数据
    不允许你还不了解指针的那些事(二)(从入门到精通看这一篇就够了)(数组传参的本质+冒泡排序+数组指针+指针数组)
    zabbix监控进阶:如何分时段设置不同告警阈值(多阈值告警)
  • 原文地址:https://blog.csdn.net/weixin_54107527/article/details/127807304