javaee入门之旅之mybatis---(5)动态SQL元素详解

1、概述

        在实际开发中,使用jdbc或其他持久层框架开发时,经常需要根据不同条件拼接SQL语句,拼接SQL语句时还要确保不能遗漏必要的空格、符号等,这种编程方式给开放人员带来很大的不便,而mybatis提供SQL语句动态组装功能,很好的解决了这个问题。

2、动态SQL元素

        动态 SQL 是 MyBatis 框架中非常重要的特性之一,mybatis采用功能强大的基于OGNL表达式来完成动态SQL,它为开发人员提供了一种灵活、可读、易于维护和高效的 SQL 查询方式,能够有效地提升开发效率和系统性能,很大程度上避免单一SQL语句的堆砌,提高SQL语句的复用性。

  1. 灵活性:动态 SQL 允许根据不同的条件动态生成不同的 SQL 查询语句,从而使得应用程序可以更加灵活地处理各种业务场景。

  2. 可读性:通过使用动态 SQL,可以将复杂的 SQL 查询语句拆分成更小的部分,并根据需要组合这些部分,使得 SQL 查询语句更加清晰易懂。

  3. 维护性:动态 SQL 可以使得 SQL 查询语句的维护变得更加容易,因为可以根据需要动态地调整和修改 SQL 查询语句的组成部分,而不需要修改大量的代码。

  4. 性能优化:通过动态生成 SQL 查询语句,可以根据具体的业务需求来优化 SQL 查询语句,从而提高查询的性能和效率。

  5. 减少 SQL 注入的风险:MyBatis 提供了参数绑定和预编译功能,可以有效地防止 SQL 注入攻击,保障系统的安全性。

常用元素

元素作用
<if>判断语句,单条件分支判断
<choose>(<when>、<otherwise>)相当于 Java 中的 switch ...case...default 语句,多条件分支判断
<where>简化SQL语句中where的条件判断
<tirm>灵活去除多余关键字
<set>用于SQL语句的动态更新
<foreach>循环语句,在in语句等列举条件常用

我的数据集数据
+-----+-------+------+
| uid | uname | uage |
+-----+-------+------+
|   1 | 张三  | 20   |
|   2 | 李四  | 18   |
+-----+-------+------+

①<if>元素

        <if> 元素是动态 SQL 中的一个常用判断元素,用于根据条件动态地包含或排除 SQL 语句的部分,类似于java中的if语句。if 元素可以在 XML 映射文件中使用,通常用于动态生成 WHERE 子句或其他条件语句。

if语句的语法:

<if test="判断条件">    SQL语句</if>
<!--在使用if元素时,只要test属性中的表达式为true,就会执行元素中的条件语句-->

在select里面使用时

<select id="findById"
            parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
         select * from users where 1=1
         <if test="uname != null and uname != ''">
             <!-- 使用 like 操作符进行模糊匹配,查询条件中的 uname 的值包含在列值中 -->
            and uname like concat('%',#{uname},'%')
         </if>

</select>

对应的测试代码

 User user1=new User();
 user1.setUname("张");
//selectList 方法用于执行查询操作,第一个参数是命名空间和 SQL 语句的 ID,第二个参数是查询条件
//List<User> users:这是一个泛型列表,用于存储查询结果 
List<User> users = session.selectList("org.example.pojo.User.findById", user1);
 for (User user:users){
        System.out.println(user);
 }

//运行结果User{uid=1, uname='张三', uage=20}

②<choose><when><otherwise>元素

        <choose><when><otherwise>元素是 MyBatis 中用于条件判断的动态 SQL 元素。它们通常一起使用,提供了一种类似于 Java 中的 switch-case 结构的功能,用于根据不同的条件执行不同的 SQL 语句片段。这三个元素往往组合使用,作用相当于java语言中的if...else   if else.

<select id="findById"
            parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
         select * from users where 1=1
         <choose>
             <when test="uname != null and uname !=''">
                 and uname like concat('%',#{uname},'%')
             </when>
             <otherwise>
                 <!-- 如果上面的条件不满足,则执行这里的语句 -->
                 and uage is not null
             </otherwise>
         </choose>

</select>

测试代码

User user1=new User();
//user1.setUname("张");
//List<User> users:这是一个泛型列表,用于存储查询结果
List<User> users = session.selectList("org.example.pojo.User.findById", user1);
for (User user:users){
       System.out.println(user);
}

//运行结果
//User{uid=1, uname='张三', uage=20}
//User{uid=2, uname='李四', uage=18}


User user1=new User();
user1.setUname("张");
//List<User> users:这是一个泛型列表,用于存储查询结果
List<User> users = session.selectList("org.example.pojo.User.findById", user1);
for (User user:users){
       System.out.println(user);
}

//运行结果
//User{uid=1, uname='张三', uage=20}

③<where>元素

        <where>元素会自动判断由组合条件拼接的SQL语句,只有where元素内的某个或多个条件成立时,才会在拼接SQL中加入where关键字,否则不会添加:即使where之后的内容有多余的and或or,where元素也会自动将他们去除。

        where、if同时使用可以进行查询、模糊查询。

<select id="findById"
            parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
      select * from users 
      <where>
          <if test="uname != null and uname != ''">
          <!-- 使用 like 操作符进行模糊匹配,查询条件中的 uname 的值包含在列值中 -->
             and uname like concat('%',#{uname},'%')
          </if>
      </where>

</select>

这个查询语句会根据传入的 uname 参数进行模糊查询,如果 uname 参数不为空,则生成的 SQL 语句会添加相应的模糊查询条件,使得查询结果符合条件,不满足的话不会添加SQL语句。

测试代码

User user1=new User();
//user1.setUname("张");
//List<User> users:这是一个泛型列表,用于存储查询结果
List<User> users = session.selectList("org.example.pojo.User.findById", user1);
for (User user:users){
       System.out.println(user);
}

//运行结果
//User{uid=1, uname='张三', uage=20}
//User{uid=2, uname='李四', uage=18}

④<trim>

        trim 元素用于在生成动态 SQL 语句时进行字符串修剪或删除。它可以帮助你动态地添加 WHERE 子句或者其他条件,同时避免不必要的空格或逗号等问题,删除多余的关键字,可以直接实现<where>元素的功能。

属性
属性说明
prefix指定SQL语句增加的前缀
prefixOverrides指定SQL语句中要去掉的前缀字符串
suffix指定给SQL语句增加的后缀
suffixOverrides指定SQL语句中要去掉的后缀字符串
<select id="findById"
            parameterType="org.example.pojo.User"
            resultType="org.example.pojo.User">
     select * from users where 1=1
     <trim prefix="where" prefixOverrides="and">
         <if test="uname != null and uname != ''">
            <!-- 使用 like 操作符进行模糊匹配,查询条件中的 uname 的值包含在列值中 -->
            and uname like concat('%',#{uname},'%')
         </if>
     </tirm>

</select>

<trim> 元素被用于动态添加 WHERE 子句。它的 prefix 设置为 "WHERE",这意味着只有在至少有一个条件被添加到 WHERE 子句时才会加上 WHERE 关键字。prefixOverrides 设置为 "AND | OR ",这意味着如果在动态 SQL 语句生成时发现以 "AND " 或 "OR " 开头的内容,它们会被删除,避免出现语法错误。

测试代码

User user1=new User();
//user1.setUname("张");
//List<User> users:这是一个泛型列表,用于存储查询结果
List<User> users = session.selectList("org.example.pojo.User.findById", user1);
for (User user:users){
       System.out.println(user);
}

//运行结果
//User{uid=1, uname='张三', uage=20}
//User{uid=2, uname='李四', uage=18}

⑤<set>元素

        <set> 元素在 MyBatis 中用于在动态 SQL 中定义要更新的字段。通常在执行 UPDATE 语句时使用,它允许你根据需要动态地设置要更新的字段,而避免了在 SQL 语句中出现不必要的逗号。

        在 UPDATE 语句中,<set> 元素内部通常包含了一系列 <if> 元素,每个 <if> 元素用于判断一个字段是否需要更新。如果某个字段需要更新,则将该字段及其新值添加到更新语句中。

<update id="UpdateById"
            parameterType="org.example.pojo.User">
     update users
        <set>
          <if test="uname != null and uname != ''">
            <!-- 使用 like 操作符进行模糊匹配,查询条件中的 uname 的值包含在列值中 -->
            uname=#{uname},
          </if>
          <if test="uage != null and uage !=''">
            uage=#{uage},
          </if>
        </set> where uid=#{uid}

</update>

根据传入的参数动态设置了要更新的字段。如果传入的 uname 参数不为空,则更新 uname 字段为传入的值;如果传入的 uage 参数不为空,则更新 uage 字段为传入的值。最后通过 WHERE 子句根据用户的 ID(uid)来定位要更新的记录。

测试代码

User user1=new User();
user1.setUid(1);
user1.setUname("张");
session.update("org.example.pojo.User.UpdateById",user1);
session.commit();
session.close();

在映射文件中使用set和if元素组合进行update语句动态SQL组装时,如果set元素内包含内容为空,则会出现SQL语法错误。所以,在使用set元素更新字段信息时,要保证传入的更新字段不能为空。

⑥<foreach>元素

        <foreach> 元素在 MyBatis 中用于迭代集合并生成相应的 SQL 片段。它可以循环遍历集合中的元素,并根据集合元素动态生成 SQL 片段,通常用于 IN 子句中的参数拼接。

属性
foreach元素属性
属性说明
item

表示集合每一个元素进行迭代时的别名,该属性必选。

index在list和数组中,index是元素序号。在map中,index是元素key
openforeach语句代码的开始符号。一般和close=”)“合用。常用在in条件语句。
separator表示元素之间的分隔符。
close表示foreach语句代码的关闭符号,一般和open=”)“合用。常用在in条件语句。

collection

用于指定遍历参数的类型。该属性取值有三种情况list、数组、map。
(1)入参为单参数且参数类型是list,collection属性值为list
<select id="findByList"
      resultType="org.example.pojo.User">
    select * from users where uid in
    <foreach collection="list" item="uid" open="(" close=")" separator=",">
        #{uid}
    </foreach>
</select>

测试代码

List<Integer> uids =new ArrayList<>();
uids.add(2);
List<User> users = session.selectList("org.example.pojo.User.findByList", uids);
for (User user:users){
    System.out.println(user);
}
session.close()
(2)入参为单参数且参数类型是数组,collection属性值为array
<select id="findByArray"
      resultType="org.example.pojo.User">
    select * from users where uid in
    <foreach collection="array" item="uid" open="(" close=")" separator=",">
        #{uid}
    </foreach>
</select>

测试代码

Integer[] uids = {2};
List<User> users = session.selectList("org.example.pojo.User.findByArray", uids);
for (User user:users){
    System.out.println(user);
}
session.close()
(3)传入参数为多参数,需把参数封装为map进行处理,collection属性值为map
    <select id="selectByMap" resultType="org.example.pojo.User">
         <!-- 定义查询语句的唯一标识符为 "selectByMap",结果类型为 org.example.pojo.User -->
        <!--uname取的map里面对应的键uname-->
        select * from users where uname=#{uname} and uid in
        <!-- 在 SQL 语句中使用 foreach 元素来循环遍历 uid 集合,rolemap表示集合里面的每个uid -->
        <foreach collection="uid" item="roleMap" open="(" close=")" separator=",">
            <!-- roleMap 是循环中当前迭代的元素,在这里表示用户 ID -->
            #{roleMap}
        </foreach>
    </select>

测试代码

//创建了一个 HashMap 对象 map 用于存储查询的参数
Map<String,Object> map =new HashMap<>();
//键 "uid" 对应的值是一个 ArrayList, List<Integer> 表示一个整数列表
List<Integer> uids =new ArrayList<>();
uids.add(1);
//将名为 "uid" 的键与先前创建的整数列表 uids 相关联,并将它们放入了一个称为 map 的 Map 对象中
map.put("uid",uids);
map.put("uname","张");
List<User> users = session.selectList("org.example.pojo.User.selectByMap", map);
for (User user:users){
    System.out.println(user);
}
//关闭session
session.close();

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值