当前位置: 首页 > news >正文

Spring学习笔记【8】

MyBatis 动态SQL

📖 目录

  • 动态SQL概述
  • if元素 - 条件判断
  • choose/when/otherwise元素 - 分支选择
  • trim元素 - 前后缀处理
  • where元素 - 智能条件处理
  • set元素 - 动态更新
  • foreach元素 - 集合遍历
  • bind元素 - 变量绑定
  • 总结

🔍动态SQL概述

动态SQL是MyBatis的核心特性之一,它能够根据不同条件动态生成SQL语句,解决了传统静态SQL在复杂业务场景下的局限性。

为什么需要动态SQL? 在实际开发中,我们经常遇到这样的场景:

  • 根据用户输入的不同条件进行查询
  • 批量操作时参数数量不确定
  • 更新操作时只更新有值的字段
  • 不同业务逻辑需要不同的SQL片段

动态SQL通过各种标签元素,让我们能够在XML映射文件中编写灵活的SQL逻辑,提高代码的复用性和可维护性。

了解动态SQL的重要性后,让我们从最基础的条件判断开始学习。

🔍if元素 - 条件判断

<if> 元素是动态SQL中最基础也是最常用的元素,用于根据条件决定是否包含某个SQL片段。

2.1 基本用法

<!-- 使用if元素,根据条件动态查询用户信息 -->
<select id="selectUserByIf" resultType="com.po.MyUser" parameterType="com.po.MyUser">select * from user where 1=1        <if test="uname != null and uname != ''">and uname like concat('%', #{uname}, '%')</if><if test="usex != null and usex != ''">and usex = #{usex}</if>
</select>

2.2 test属性详解

test 属性中可以使用的表达式:

  • 空值判断uname != nulluname == null
  • 字符串判断uname != ''uname == ''
  • 数值比较age > 18score >= 60
  • 逻辑运算andornot

注意事项:

  • 使用 1=1 作为基础条件,避免第一个条件前的 and 造成语法错误
  • 字符串类型建议同时判断 != null!= ''
  • 数值类型只需判断 != null

🔍choose/when/otherwise元素 - 分支选择

当需要在多个条件中选择一个执行时,使用 <choose> 元素,类似于Java中的 switch-case 语句。

3.1 基本结构

<!-- 使用choose、when、otherwise元素,根据条件动态查询用户信息 -->
<select id="selectUserByChoose" resultType="com.po.MyUser" parameterType="com.po.MyUser">select * from user where 1=1        <choose><when test="uname != null and uname != ''">and uname like concat('%', #{uname}, '%')</when><when test="usex != null and usex != ''">and usex = #{usex}</when><otherwise>and uid > 10</otherwise></choose>
</select>

3.2 执行逻辑

  • <choose> 相当于 switch
  • <when> 相当于 case,按顺序检查条件
  • <otherwise> 相当于 default,当所有 when 条件都不满足时执行

使用场景:

  • 多个互斥条件中选择一个
  • 设置默认查询条件
  • 根据不同条件使用不同的排序方式

🔍trim元素 - 前后缀处理

<trim> 元素提供了强大的前后缀处理能力,是处理动态SQL中最灵活的元素。

4.1 属性说明

<!-- 使用trim元素,根据条件动态查询用户信息 -->
<select id="selectUserByTrim" resultType="com.po.MyUser" parameterType="com.po.MyUser">select * from user      <trim prefix="where" prefixOverrides="and |or "><if test="uname != null and uname != ''">  and uname like concat('%', #{uname}, '%')</if><if test="usex != null and usex != ''">  and usex = #{usex} </if></trim>
</select>

属性详解:

  • prefix:在内容前添加指定前缀(如 “where”)
  • suffix:在内容后添加指定后缀
  • prefixOverrides:去除内容开头的指定字符(如 "and "、"or ")
  • suffixOverrides:去除内容结尾的指定字符(如 “,”)

4.2 应用场景

<!-- 动态插入语句 -->
<insert id="insertUser" parameterType="com.po.MyUser">insert into user<trim prefix="(" suffix=")" suffixOverrides=","><if test="uname != null">uname,</if><if test="usex != null">usex,</if><if test="uage != null">uage,</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="uname != null">#{uname},</if><if test="usex != null">#{usex},</if><if test="uage != null">#{uage},</if></trim>
</insert>

🔍where元素 - 智能条件处理

<where> 元素是 <trim> 的简化版本,专门用于处理查询条件

5.1 基本用法

<!-- 使用where元素,根据条件动态查询用户信息 -->
<select id="selectUserByWhere" resultType="com.po.MyUser" parameterType="com.po.MyUser">select * from user      <where><if test="uname != null and uname != ''">and uname like concat('%', #{uname}, '%')</if><if test="usex != null and usex != ''">and usex = #{usex}</if></where>
</select>

5.2 智能处理

<where> 元素会智能地处理以下情况:

  • 当包含内容为空时,不会生成 where 关键字
  • 自动去除开头的 andor
  • 只有当包含内容不为空时才生成 where 子句

等价的trim写法:

<trim prefix="where" prefixOverrides="and |or "><!-- 内容 -->
</trim>

🔍set元素 - 动态更新

<set> 元素专门用于动态更新操作,能够智能处理更新字段。

6.1 基本用法

<!-- 使用set元素,动态修改一个用户 -->
<update id="updateUserBySet" parameterType="com.po.MyUser">update user     <set><if test="uname != null">uname = #{uname},</if><if test="usex != null">usex = #{usex},</if><if test="uage != null">uage = #{uage},</if></set>where uid = #{uid}  
</update>

6.2 智能处理特性

  • 自动添加 SET 关键字
  • 自动去除最后一个多余的逗号
  • 防止生成空的 SET 子句

🔍foreach元素 - 集合遍历

<foreach> 元素用于遍历集合,常用于 IN 查询、批量插入等场景。

7.1 基本用法

<!-- 使用foreach元素,查询用户信息 -->
<select id="selectUserByForeach" resultType="com.po.MyUser" parameterType="List">select * from user where uid in     <foreach item="item" index="index" collection="list" open="(" separator="," close=")">#{item}</foreach>
</select>

7.2 属性详解

属性说明示例值
collection指定要遍历的集合类型list/array/map
item集合中每个元素的变量名item/user
index当前元素的索引位置index/i
open遍历开始时的拼接字符(
close遍历结束时的拼接字符)
separator元素之间的分隔符,

7.3 collection属性规则

collection的值取决于参数类型

  • 单个List参数collection="list"
  • 单个Array参数collection="array"
  • Map参数collection="map中的key"
  • 对象属性collection="对象.属性名"

🔍bind元素 - 变量绑定

<bind> 元素用于创建变量并绑定到上下文中,主要解决模糊查询中的SQL注入问题和数据库兼容性问题。

8.1 解决的问题

传统方式的问题:

  • 使用 ${} 拼接存在SQL注入风险
  • 不同数据库的字符串拼接函数不同(MySQL的concat、Oracle的||

8.2 基本用法

<!-- 使用bind元素进行模糊查询 -->
<select id="selectUserByBind" resultType="com.po.MyUser" parameterType="com.po.MyUser"><!-- bind中uname是com.po.MyUser的属性名,paran_uname是自定义变量名 --><bind name="paran_uname" value="'%' + uname + '%'"/>select * from user where uname like #{paran_uname}  
</select>

8.3 表达式语法

<bind>value 属性支持:

  • 字符串拼接'%' + name + '%'
  • 条件表达式age > 18 ? '成年' : '未成年'
  • 对象属性访问user.name + '(' + user.id + ')'
  • 方法调用name.toLowerCase()

🔍总结

MyBatis动态SQL通过不同的标签元素实现了灵活的SQL生成:

元素作用适用场景核心特性
<if>条件判断根据条件包含SQL片段简单条件判断
<choose>分支选择多个条件中选择一个类似switch-case
<trim>前后缀处理灵活的前后缀管理高度可定制化
<where>条件子句动态生成WHERE条件智能处理and/or
<set>更新子句动态UPDATE操作智能处理逗号
<foreach>集合遍历批量操作、IN查询支持多种集合类型
<bind>变量绑定模糊查询、变量处理防SQL注入,跨数据库兼容

最后希望这份笔记能给你带来微薄的帮助!🎉

相关文章:

  • 九江网站建设求职简历360信息流广告平台
  • 那个网站做旅游规划好灯塔seo
  • 做ppt比较好的网站有哪些网络营销策略分析
  • 企业网站建设报价郑州新闻发布
  • 整合营销经典案例seo如何优化图片
  • 关于服饰搭配做的比较好的网站我想自己建立一个网站
  • 八股文——JAVA基础:基本数据类型与包装类的区别
  • 【Ansible】Ansible入门
  • 数的范围(连续数字边界)
  • OceanBase向量检索在货拉拉的探索和实践
  • 论文阅读:A Survey on Large Language Models for Code Generation
  • PYTHON从入门到实践5-列表操作
  • DDNS-GO 使用教程:快速搭建属于自己的动态域名解析服务(Windows 版)
  • SpringBoot基于JavaWeb的城乡居民基本医疗信息管理系统
  • 《汇编语言:基于X86处理器》第4章 复习题和练习,编程练习
  • 工作流引擎技术方案<初版>
  • 逆向入门(8)汇编篇-rol指令的学习
  • JVM 中的 GC 算法演进之路!(Serial、CMS、G1 到 ZGC)
  • 基于 opencv+yolov8+easyocr的车牌追踪识别
  • WinAppDriver 自动化测试:Python篇
  • 达梦数据库安装
  • 【网络实验】-配置用户登录
  • 《高等数学》(同济大学·第7版)第九章 多元函数微分法及其应用第一节多元函数的基本概念
  • UniApp 开发第一个项目
  • 【kubernetes】--Service
  • MySQL为什么默认引擎是InnoDB?