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

embedded/2024/10/10 21:25:42/
xmlns="http://www.w3.org/2000/svg" style="display: none;">

目录

  • 前言
  • 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
xml"><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语句,允许你在多个条件中选择一个来执行
xml"><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查询等
xml"><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语句,自动去掉多余的逗号
xml"><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>将整个列表插入或作为查询条件,这会导致内存问题

xml"><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切分为较小的块
java">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拼接,从而带来性能问题或安全隐患

  • 基本的注解校验
java">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注解,可以自动在控制层或服务层进行参数校验
java">@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");
}
  • 自定义校验逻辑:有时内置的注解不够,可以自定义校验注解
    例如,限制用户名长度或格式
java">@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.ppmy.cn/embedded/119244.html

相关文章

学生宿舍管理:Spring Boot技术驱动

第2章 开发环境与技术 学生宿舍管理系统的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对学生宿舍管理系统用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&#xff0c;是经常变动的&#xff0c;没…

Linux驱动开发(速记版)--驱动基础

第一章 初识内核源码 Linux系统源码提供了操作系统的核心功能&#xff0c;如进程管理、内存管理、文件系统等。 BusyBox这类的文件系统构建工具&#xff0c;则提供了在这些核心功能之上运行的一系列实用工具和命令&#xff0c;使得用户能够执行常见的文件操作、文本处理、网络配…

TryFastGPT大模型介绍

目录 一、TryFastGPT大模型介绍 1. 开发团队 2. 发展史 3. 基本概念 4. 架构 5. 使用案例 6. 安装步骤 二、TryFastGPT与其他大模型的对比 三、总结 一、TryFastGPT大模型介绍 1. 开发团队 TryFastGPT由TryAI团队开发&#xff0c;该团队由多位在人工智能和自然语言处…

【C语言从不挂科到高绩点】23-指针05-结构体指针【重点知识】

Hello!彦祖们,俺又回来了!!!,继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中非常重要的知识点-指针: 本套课程将会从0基础讲解C语言核心技术,适合人群: 大学中开设了C语言课程的同学想要专升本或者考研的同学想要考计算机等级证书的同学想…

基于微信小程序的教学质量评价系统ssm(lw+演示+源码+运行)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的教学质量评价系统的开发全过程。通过分析基于微信小程序的教学质量评价系统管理的不足&#xff0c;创建了一个计算机管理基于微信小程序的教学…

【rust】 基于rust编写wasm,实现markdown转换为html文本

文章目录 背景转换预览核心代码前置依赖rustup换源 cargo本地路径修改&#xff08;可选&#xff09;cargo换源中科大 wasm-pack安装 背景 尝试用rust编写一款markdown转html的插件&#xff0c;通过wasm给html使用&#xff0c;不得不说体积挺小&#xff0c;约200K&#xff0c; …

JMeter压测HTTPS 在window 11处理SSL证书认证

在此位置&#xff0c;找到chrome 的证书 证书到出到指定的路径&#xff0c; 利用jdk中的keytool.exe工具&#xff0c;重新生成证书 crm 去到命令窗口&#xff0c;再去到JDK路径下&#xff0c;如下 输入 keytool -import -alias “zhengshu.store” -file “D:\Program F…

零基础学Axios

Axios官网&#xff1a;Axios官网 想用Axios前需要在项目中安装axios,安装方式如下&#xff1a; 下列是axios请去方式&#xff0c;本文主要讲解post和get请求&#xff0c;其他请求和这两种请求方法相同。 1 get请求 1.1 不带请求参数 前端 后端 1.2 带请求参数 前端 写法…