引言

在复杂业务场景中,SQL查询往往需要动态拼接条件、复用代码片段,并支持批量操作。MyBatis的动态SQL功能提供了强大的解决方案,本文将深入解析<choose>条件分支、<sql>片段复用、批量操作优化等核心技巧,助你写出高效、可维护的SQL映射。

一、条件分支:choose / when / otherwise标签

1.1 场景说明

假设需要实现一个商品查询接口,支持以下条件组合:

  • 按名称模糊查询
  • 按价格区间查询
  • 按状态精确查询
  • 若无条件则返回所有商品

1.2 动态SQL实现

<select id="selectGoods" resultType="Goods">SELECT * FROM goods<where><choose><when test="name != null">AND name LIKE CONCAT('%', #{name}, '%')</when><when test="minPrice != null and maxPrice != null">AND price BETWEEN #{minPrice} AND #{maxPrice}</when><when test="status != null">AND status = #{status}</when><otherwise>AND is_deleted = 0  <!-- 默认未删除 --></otherwise></choose></where>
</select>

1.3 执行流程解析

  1. <choose>标签内按顺序匹配第一个满足的<when>条件
  2. 若所有<when>均不满足,则执行<otherwise>
  3. <where>标签自动处理前缀AND/OR及空条件

二、SQL片段复用:sql标签与include标签

2.1 场景说明

多个查询需要复用以下内容:

  • 基础字段列表(id, name, price)
  • 公共过滤条件(未删除)

2.2 定义与引用

<!-- 定义SQL片段 -->
<sql id="Base_Column_List">id, name, price, status, create_time
</sql><sql id="Common_Where">AND is_deleted = 0
</sql><!-- 引用片段 -->
<select id="selectGoodsList" resultType="Goods">SELECT <include refid="Base_Column_List"/>FROM goods<where><include refid="Common_Where"/><if test="categoryId != null">AND category_id = #{categoryId}</if></where>
</select>

2.3 进阶用法:带参数的SQL片段

<sql id="Price_Filter"><if test="minPrice != null">AND price >= #{minPrice}</if><if test="maxPrice != null">AND price <= #{maxPrice}</if>
</sql><!-- 使用时 -->
<select id="selectByPrice" resultType="Goods">SELECT * FROM goods<where><include refid="Common_Where"/><include refid="Price_Filter"/></where>
</select>

三、批量操作优化

3.1 批量插入优化

传统单条插入(低效)
<insert id="insertGoods" parameterType="Goods">INSERT INTO goods (name, price) VALUES (#{name}, #{price})
</insert>

Java调用:

for (Goods goods : list) {goodsMapper.insertGoods(goods);
}
批量插入(高效)
<insert id="batchInsert" parameterType="java.util.List">INSERT INTO goods (name, price) VALUES<foreach collection="list" item="item" separator=",">(#{item.name}, #{item.price})</foreach>
</insert>

3.2 批量更新优化

<update id="batchUpdatePrice" parameterType="java.util.List"><foreach collection="list" item="item" separator=";">UPDATE goodsSET price = #{item.newPrice}WHERE id = #{item.id}</foreach>
</update>

3.3 性能关键配置

在JDBC URL中添加批处理参数:

jdbc.url=jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=true

MyBatis全局配置启用批量模式:

<settings><setting name="defaultExecutorType" value="BATCH"/>
</settings>

四、性能优化建议

  1. 减少动态SQL嵌套

    • 避免在<foreach>中嵌套其他动态标签
    • 复杂逻辑优先在Java层处理
  2. 合理使用缓存

    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
    
  3. 批量操作最佳实践

    try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {GoodsMapper mapper = session.getMapper(GoodsMapper.class);for (Goods goods : list) {mapper.update(goods);}session.commit();
    }
    

五、完整示例代码

// GoodsMapper.java
public interface GoodsMapper {List<Goods> selectGoods(@Param("name") String name,@Param("minPrice") BigDecimal minPrice,@Param("maxPrice") BigDecimal maxPrice,@Param("status") Integer status);int batchInsert(@Param("list") List<Goods> goodsList);
}
<!-- GoodsMapper.xml -->
<mapper namespace="com.example.mapper.GoodsMapper"><sql id="Base_Column_List">id, name, price, status, create_time</sql><select id="selectGoods" resultType="Goods">SELECT <include refid="Base_Column_List"/>FROM goods<where><choose><when test="name != null">name LIKE CONCAT('%', #{name}, '%')</when><when test="minPrice != null and maxPrice != null">price BETWEEN #{minPrice} AND #{maxPrice}</when><otherwise>status = 1</otherwise></choose></where></select><insert id="batchInsert" parameterType="list">INSERT INTO goods (name, price) VALUES<foreach collection="list" item="item" separator=",">(#{item.name}, #{item.price})</foreach></insert>
</mapper>

六、总结

技术点适用场景性能影响最佳实践
<choose>多条件分支选择优先处理高频条件
<sql>复用字段/条件复用避免过度抽象
批量插入大数据量写入配合JDBC批处理参数
动态SQL缓存重复执行的动态查询设置合理的flushInterval

通过灵活运用MyBatis的动态SQL特性,可显著提升复杂查询场景的开发效率和运行性能。实际开发中需根据数据量、查询复杂度、并发量等因素综合选择优化策略。

mybatis基础专栏就结束啦,期待下我下专栏mybatis进阶,感情到一定阶段了,可以深入了解一下了!🤔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/89931.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/89931.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/89931.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@Transactional 注解失效的场景及原因分析

先分析一下 1&#xff0c;内部调用&#xff0c;原对象调用&#xff0c;不是代理对象调用 2&#xff0c;private方法&#xff0c;源码中&#xff0c;只能是public方法 3&#xff0c;异常被捕获了&#xff0c;事物拦截器&#xff0c;无法感知 4&#xff0c;子线程调用&#x…

使用unity创建项目,进行动画制作

1. 创建unity项目 error: error CS0006: Metadata file Library/PackageCache/com.unity.collab-proxy2.8.2/Lib/Editor/PlasticSCM/log4netPlastic.dll could not be found error CS0006: Metadata file Library/PackageCache/com.unity.collab-proxy2.8.2/Lib/Editor/Plasti…

Centos系统及国产麒麟系统设置自己写的go服务的开机启动项完整教程

1、创建服务文件 在 /etc/systemd/system/ 下新建服务配置文件&#xff08;需sudo权限&#xff09;&#xff0c;例如&#xff1a; sudo nano /etc/systemd/system/mygo.service 如下图&#xff0c;创建的mygo.service 2、创建内容如下&#xff1a; DescriptionThe go HTTP a…

Java面试宝典: IO流

1. 下面哪个流类属于面向字符的输入流() 选项: A. BufferedWriter B. FileInputStream C. ObjectInputStream D. InputStreamReader 答案:D 详细分析: 字符流与字节流的本质区别: 字符流(Character Streams)以Unicode字符为单位操作数据,适用于文本处理字节流(Byte…

黑马python(二十五)

目录&#xff1a;1.数据输出-输出为Python对象2.数据输出-输出到文件中3.综合案例1.数据输出-输出为Python对象2.数据输出-输出到文件中移动文件到文件夹&#xff1a;生成了好多文件&#xff0c;因为Rdd是有分区的 &#xff0c;会把数据分散到各个分区去存储&#xff0c;因为电…

【LeetCode 热题 100】41. 缺失的第一个正数——(解法一)暴力解

Problem: 41. 缺失的第一个正数 题目&#xff1a;给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(N log N)…

在运行 Laravel Sail 前,需安装 Docker Desktop 并完成基础配置/具体步骤

一、安装 Docker Desktop&#xff08;必备环境&#xff09; Windows 系统 &#xff08;windows安装包 有两个版本&#xff09; 架构版本查看 1. Win R‌ 输入 ‌cmd‌ 打开命令提示符&#xff1b; 2. ‌输入命令‌&#xff1a; bash echo %PROCESSOR_ARCHITECTURE% 3. ‌结果…

AI 应用于进攻性安全

一、引言 大语言模型&#xff08;LLM&#xff09;和 AI 智能体的出现推动进攻性安全变革&#xff0c;其在侦察、扫描、漏洞分析、利用、报告五个阶段展现出数据分析、代码生成、攻击场景规划等能力&#xff0c;能提升安全团队效率与扩展性&#xff0c;但存在 “幻觉” 等局限性…

微控制器中的EXTI0(External Interrupt 0)中断是什么?

微控制器中的EXTI0(External Interrupt 0)中断是什么? EXTI0(External Interrupt 0) 是微控制器(如STM32等ARM Cortex-M系列芯片)中的一个外部中断线,专门用于处理来自特定GPIO引脚的外部信号触发中断。以下是详细说明: 1. 基本概念 EXTI(External Interrupt/Event …

EasyGBS平台内置AI算法了,算法成为了视频平台的标配

今年五一的时候立了个flag&#xff08;《国标GB28181平台EasyGBS未来研发方向在哪&#xff1f;》&#xff09;&#xff0c;我想不能再局限在只是满足于传统视频平台的功能&#xff0c;传统的EasyGBS也就是接入几种视频协议&#xff0c;什么RTSP、ONVIF、RTMP、GB28181这些&…

C# 常量与变量

在 C# 中&#xff0c;常量和变量是存储数据的基本方式&#xff1a; // 常量&#xff1a;使用 const 关键字声明&#xff0c;必须在声明时初始化&#xff0c;且值不能改变 const double Pi 3.14159; const string Message "Hello, World!"; ​ // 变量&#xff1a;…

TensorRT-LLM:大模型推理加速的核心技术与实践优势

大型语言模型推理就像让一头300公斤的大熊猫玩平衡木——显存消耗和计算效率这对双胞胎问题随时可能让表演翻车。以主流的7B参数模型为例&#xff0c;FP16精度下仅模型权重就吃掉14GB显存&#xff0c;这还没算上推理过程中不断膨胀的KV Cache——当处理2048长度的对话时&#x…

免费棱光 PDF:免安装 加水印 去水印 批量格式转换

各位办公小能手们&#xff0c;今天给大家介绍一款超棒的PDF处理工具——棱光PDF&#xff01;它完全免费&#xff0c;专门解决咱对PDF文件的常见操作需求。绿色免安装&#xff0c;体积小得跟颗花生米似的&#xff0c;打开就能用。它有三大核心功能&#xff0c;分别是水印管理、格…

(二)复习(Error Pattern/Result Pattern/)

文章目录 项目地址一、Error Pattern1.1 定义Error类1. ErrorType 可发生的错误类型2. Error类3. ValidataionError1.2 给每个实体创建Error类1. CategoryError类2. TicketErrror类3. EventErrror类二、Result Pattern1.1 自定义返回Result1. 泛型类2. 泛型方法1.2 Api层的Resu…

20250705-day6

NATO&#xff1a;北大西洋公约组织 Software Crisis&#xff1a;软件危机 Paradigm&#xff1a;设计范型 Waterfall Model&#xff1a;瀑布模型 Prototype Model&#xff1a;原型模型&#xff08;又称快速模型&#xff09; Spiral Model&#xff1a;螺旋模型 Agile&#xff1a;…

视频播放中时钟的概念及音视频同步概念

author: hjjdebug date: 2025年 07月 05日 星期六 18:20:45 CST descrip: 视频播放中时钟的概念及音视频同步概念 文章目录 1.前言: 视频播放:1. 固定延时时间2. 根据frame的duration来延时.3. 根据frame的PTS 来播放3.1. 时钟是什么?3.2. 时钟的用途. 2.音视频同步: 1.前言: …

Python基础之字符串操作全解析

在 Python 中&#xff0c;字符串是最常用的数据类型之一&#xff0c;掌握字符串的各种操作对于日常编程至关重要。本文将详细介绍 Python 字符串的类型特性、编码转换、常用运算符及方法&#xff0c;帮助你全面掌握字符串处理技巧。 一、字符串的基本类型 Python 中的字符串属…

【爬虫】逆向爬虫初体验之爬取音乐

寻找数据 打开F12中的网络页面&#xff0c;播放音乐后&#xff0c;筛选媒体&#xff0c;会发现当前这首歌曲音频链接地址&#xff0c;打开后&#xff0c;点击“标头”就能能看到请求URL 截取“.mp3”前面的一部分进行搜索&#xff0c;搜索出来了很多数据包&#xff0c;但都是…

CppCon 2018 学习:Fancy Pointers for Fun and Profit

“Fancy Pointers for Fun and Profit” 这个标题听起来像是在讨论**“高级指针用法”**&#xff0c;尤其是在C里&#xff0c;如何利用智能指针、定制指针类型&#xff0c;或者其他高级指针技巧来写更安全、更高效、更优雅的代码。 可能的理解和内容方向&#xff1a; 1. 什么是…

思辨场域丨数字信号技术重塑农林牧渔:从“靠天吃饭”到“靠数吃饭”

凌晨三点&#xff0c;山东莱芜的养猪户老李被手机震动惊醒。屏幕显示&#xff1a;3号猪舍&#xff0c;母猪即将分娩。他轻点屏幕启动远程监控&#xff0c;翻身继续入睡——而在几年前&#xff0c;这样的夜晚他只能在猪圈里守着。 清晨的茶园里&#xff0c;兴业县的茶农王大姐掏…