详细分析Mybatis中的动态Sql(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. 注意事项
  • 3. 拓展

前言

以往的Java基本知识推荐阅读:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)
  3. Mybatis从入门到精通(全)
  4. MyBatis-plus从入门到精通(全)

1. 基本知识

在MyBatis中,动态SQL是一种强大的功能,允许在<select>, <insert>, <update>, <delete> 等标签中根据条件动态构建SQL语句

这种动态性可以简化数据库查询的复杂度,避免硬编码查询逻辑

MyBatis 提供了几种常用的动态 SQL 标签,用来处理条件判断、循环和字符串拼接等操作:

  • <if>标签:根据给定的条件动态拼接SQL
<select id="findUsers" resultType="User">SELECT * FROM users<where><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>
  • <choose>, <when>, <otherwise>标签:类似于Java中的switch语句,允许你在多个条件中选择一个来执行
<select id="findUsersByStatus" resultType="User">SELECT * FROM users<where><choose><when test="status != null">AND status = #{status}</when><otherwise>AND status = 'active'</otherwise></choose></where>
</select>
  • <foreach>标签:用于处理循环,一般用来遍历集合构建IN查询等
<select id="findUsersByIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="id" collection="list" open="(" separator="," close=")">#{id}</foreach>
</select>

<trim>, <where>, <set>标签:

  • <trim>:去掉拼接后多余的前后缀
  • <where>:自动在拼接后的条件前加WHERE,并去除多余的AND
  • <set>:主要用于UPDATE语句,自动去掉多余的逗号
<update id="updateUser">UPDATE users<set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if></set>WHERE id = #{id}
</update>

2. 注意事项

使用此种方式需要注意动态SQL带来的OOM风险

在复杂动态SQL的构建中,特别是当涉及大批量数据或复杂拼接时,容易导致内存溢出(OOM)问题
尤其是在<foreach>中处理大量数据时,如果不加以控制,可能会占用大量内存

假设有一个非常大的List,例如数百万条数据
如果在MyBatis中直接使用<foreach>将整个列表插入或作为查询条件,这会导致内存问题

<select id="findLargeUsersByIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="id" collection="list" open="(" separator="," close=")">#{id}</foreach>
</select>

在这种情况下,MyBatis会尝试将数百万个id拼接到一个SQL语句中,导致内存占用过高,最终导致OOM

规避OOM的方法

  1. 分页处理:可以将大批量数据分段处理,例如在代码中将list切分为较小的块
List<List<Integer>> partitionedIds = Lists.partition(largeIdsList, 1000);
for (List<Integer> idsBatch : partitionedIds) {userMapper.findLargeUsersByIds(idsBatch);
}
  1. 避免过大的IN查询:IN查询是常见的OOM来源,可以通过数据库表连接等方式优化查询。

  2. 懒加载:通过懒加载策略,避免一次性加载过多数据到内存中

3. 拓展

在Java代码中,进行参数校验是一种很好的实践,尤其是在使用动态SQL时,如果不校验传入的参数,可能会导致意外的SQL拼接,从而带来性能问题或安全隐患

  • 基本的注解校验
public class User {@NotNull(message = "Name cannot be null")private String name;@Min(value = 18, message = "Age should not be less than 18")private Integer age;
}

在使用这些注解后,如果传入的参数不符合条件,就会抛出ConstraintViolationException

  • 结合Spring的@Valid注解,可以自动在控制层或服务层进行参数校验
@PostMapping("/createUser")
public ResponseEntity<?> createUser(@Valid @RequestBody User user, BindingResult result) {if (result.hasErrors()) {return new ResponseEntity<>(result.getAllErrors(), HttpStatus.BAD_REQUEST);}userService.createUser(user);return ResponseEntity.ok("User created successfully");
}
  • 自定义校验逻辑:有时内置的注解不够,可以自定义校验注解
    例如,限制用户名长度或格式
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UsernameValidator.class)
public @interface ValidUsername {String message() default "Invalid username";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}public class UsernameValidator implements ConstraintValidator<ValidUsername, String> {public void initialize(ValidUsername constraint) {}public boolean isValid(String username, ConstraintValidatorContext context) {return username != null && username.matches("^[a-zA-Z0-9]+$");}
}

总的来说

MyBatis中的动态SQL功能非常灵活,但也存在潜在的性能和内存问题
在复杂查询中,务必小心处理大量数据操作,合理运用分页、懒加载等技术
在Java代码层面,通过参数校验来确保数据的安全和正确性,是防止问题发生的关键步骤

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

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

相关文章

H5 随机身份证号码、社会统一信用代码、手机号、名字、银行卡号码

平时注册可能会用到这些&#xff0c;原本用自己服务器搭了个&#xff0c;感觉纯前端的还能引入到项目中挺好的&#xff0c;之后再追加一些常用的随机数据&#xff0c;这样写表单应该就会好测试了(●’◡’●)。 在线链接 https://linyisonger.github.io/H5.Examples/?name./07…

java:缓存 json格式

以下是修改后的代码&#xff1a; import org.apache.ibatis.session.SqlSession; import org.springframework.data.redis.core.RedisTemplate; import com.alibaba.fastjson.JSON; import java.util.List; import java.util.stream.Collectors; import java.util.logging.Logg…

Python中的`super()`函数:掌握面向对象编程的艺术

引言 在Python面向对象编程中&#xff0c;super()函数主要用于调用基类&#xff08;父类&#xff09;的方法或属性&#xff0c;尤其在处理复杂的多重继承时显得尤为有用。通过合理使用super()&#xff0c;我们可以轻松地管理方法调用顺序&#xff0c;避免重复代码&#xff0c;…

Brave编译指南2024 MacOS篇-初始化构建环境(五)

引言 在上一篇文章中&#xff0c;我们完成了Brave浏览器编译所需的环境配置。现在&#xff0c;我们将进入下一个关键阶段&#xff1a;初始化构建环境。这个步骤将确保我们有一个完整的、准备就绪的开发环境&#xff0c;包括所有必要的依赖项和Chromium源代码。 1. 切换工作目…

上海沪鑫餐饮供应链:嘉定蔬菜配送分拣工作的精细艺术

在餐饮行业的背后&#xff0c;有一条默默运作的关键链条——餐饮供应链。而在上海沪鑫餐饮管理有限公司&#xff08;简称沪鑫餐饮供应链、沪鑫食材&#xff09;中&#xff0c;嘉定蔬菜配送分拣工作犹如一场精心编排的舞蹈&#xff0c;每一个动作都决定着最终呈现在餐桌上的美食…

文件和目录

文件和目录 获取文件属性 通过 ls 命令可以查看到文件的很多属性内容&#xff0c;这些文件属性的内容可以通过以下几个函数获取: #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>int stat(const char *pathname, struct stat *statbuf…

【前端】ES6:Proxy代理和Reflect对象

文章目录 1 Proxy代理1.1 get方法1.2 set方法1.3 has方法1.4 this问题 2 Reflect对象2.1 代替Object的某些方法2.2 修改某些Object方法返回结果2.3 命令式变为函数行为2.4 配合Proxy 1 Proxy代理 Proxy如其名&#xff0c;它的作用是在对象和和对象的属性值之间设置一个代理&am…

ISA Server配置https踩坑全过程

首先普通的http配置请参考 【ISA Server 2006发布Web网站】 https://www.bilibili.com/video/BV1qc411v75w/?share_sourcecopy_web&vd_sourcef35b2f2d0d34140bcba81b8b6f8c1b69 本文只一笔带过&#xff0c;讲一下https部分。 正解 由于我维护的是windows server 2003的…

计算机毕业设计 招生宣传管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

大数据复习知识点1

1、HDFS和MapReduce的起源&#xff1a;HDFS起源于Google的GFS论文&#xff0c;它是为了解决大规模数据集的存储问题而设计的。而MapReduce则是Google为了解决大规模数据处理问题而提出的一种并行计算模型。 2、YARN的作用&#xff1a;YARN是Hadoop的资源管理器&#xff0c;它负…

C语言扫盲

文章目录 C版本C语言特征GCCprintf数据类型函数指针内存管理void指针 Struct结构和Union结构typedef预处理器make工具cmake工具Projectintegral of sinc functionemulator embedded systeman event schedule 补充在线Linux终端安装Linux参考 建议还是国外教材学习…人家的PPT比…

物联网系统中OLED屏主流驱动方案详解

01 物联网系统中为什么要使用OLED驱动芯片 卓越的显示效果 1、高对比度和鲜艳色彩&#xff1a;OLED屏幕能够自发光&#xff0c;因此能够实现极高的对比度和鲜艳的色彩表现&#xff0c;这在物联网设备的显示界面上尤为重要&#xff0c;可以为用户提供更清晰、更生动的视觉体验…

[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor

期刊名称&#xff1a;IEEE Transactions on Information Forensics and Security 发布链接&#xff1a;TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名&#xff1a;TorWard&#xff1a;…

Android Studio中断点调试

1. Source 2. lunch 3. mmm development/tools/idegen 4. ./development/tools/idegen/idegen.sh 这一步会在源码主目录下生成android.iml和android.ipr 5. 修改android.iml文件 由于我们一般调试的是frameworks/base/core和frameworks/base/services目录&#xff0c;故我…

jvm专题 之 内存模型

文章目录 前言一个java对象的运行过程jvm内存分布程序的基本运行程序对象什么是对象对象的创建一、类加载检查二、对象内存分配三、初始化零值四、设置对象头五、执行初始化方法 对象的访问定位 对象与类的关系由类创建对象的顺序 对象的创建 前言 一个程序需要运行&#xff0…

JNI实现Java调用C++函数

1. 测试环境 操作系统&#xff1a;win10JDK版本&#xff1a;JDK11 安装教程gcc版本&#xff1a;8.1.0 2. 声明native方法 // HelloJNI.java public class HelloJNI {// 输出Hello JNI from CPP. private native static void sayHello();// 实现两个整数相加private native s…

Android手机投屏方案实现方式对比

文章目录 1.概述2.术语解释2.1 miracast2.2 scrcpy2.4 Wifi Direct2.5 app_process 3.技术实现对比3.1 Miracast3.1.1 Miracast介绍3.1.2 Miracast原理3.1.3 Miracast优缺点分析 3.2 Scrcpy3.2.1 scrcpy 介绍3.2.2 scrcpy的实现原理3.2.3 scrcpy的优缺点分析 3.3 Google cast3.…

【学习笔记】手写 Tomcat 四

目录 一、Read 方法返回 -1 的问题 二、JDBC 优化 1. 创建配置文件 2. 创建工具类 3. 简化 JDBC 的步骤 三、修改密码 优化返回数据 创建修改密码的页面 注意 测试 四、优化响应动态资源 1. 创建 LoginServlet 类 2. 把登录功能的代码放到 LoginServlet 类 3. 创…

Python 算法交易实验89 QTV200日常推进-模式思考

说明 过去几天大A的表现还是比较戏剧化的。 让我想到了&#xff1a; 1 价稳量缩模式。之前很长一段时间都是这种状态&#xff0c;最终还是大爆发了&#xff0c;这个可取。2 周期模式。假设价格是一个周期为T(T可变)的正弦波&#xff0c;所以最终还是回到了几个月前的位置&…

软件测试分类极简理解

基础 - 测试分类&#xff08;4 种&#xff09; 1、功能测试&#xff08;难度&#xff1a;2&#xff09; 功能测试用于测试软件的功能是否满足需求规格说明书 它验证软件是否能够执行预期的操作 2、性能测试&#xff08;难度&#xff1a;4&#xff09; 性能测试用于测试软件…