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

在Mybatis plus中如何使用自定义Sql

在演示UpdateWrapper的案例中,我们在代码中编写了更新的SQL语句:

@Test
void testUpadateWrapper(){List<Long> ids = List.of(1L,2L,4L);//生成SQLUpadateWrapper<User> wrapper =new UpdateWrapper<User> ().setSql("balance =balance -200").in("id",ids);// 第一个参数可以给null  不填更新字段和数据  
userMapper.update(null,wrapper);
}

​这种写法在企业中不允许 因为Sql语句最好都在持久层而不是业务层

由于条件是in语句,只能将Sql写在Mapper.xml文件中然后使用foreach来生成动态的SQL

所以,MybatisPlus提供了自定义SQL功能,可以让我们利用Wrapper生成查询条件,再结合Mapper.xml编写SQL

@Test
void testCustomWrapper() {// 1.准备自定义查询条件List<Long> ids = List.of(1L, 2L, 4L);QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);// 2.调用mapper的自定义方法,直接传递WrapperuserMapper.deductBalanceByIds(200, wrapper);
}

​然后在UserMapper中自定义SQL:、

package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Param;public interface UserMapper extends BaseMapper<User> {@Select("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}")void deductBalanceByIds(@Param("money") int money, @Param("ew") QueryWrapper<User> wrapper);
}

扩展ew.customSqlSegment

${ew.customSqlSegment} 是 MyBatis-Plus 中用于集成条件构造器(QueryWrapper 或 LambdaQueryWrapper)的核心占位符,主要作用是

1. 动态拼接 SQL 条件片段

2.实现 "自定义 SQL 骨架 + 动态条件拼接" 的灵活查询。

3.无需大量的手写<if>标签判断条件是否存在,简化SQL编写

4.支持复杂的条件逻辑

例如:

wrapper.eq("status", 1).and(i -> i.like("name", "张").or().like("name", "李"));

等价于

WHERE status = 1 AND (name LIKE '%张%' OR name LIKE '%李%')

多表关联

利用Wrapper中自定义条件结合自定义SQL实现多表查询的效果

例如,我们要查询出所有收货地址在北京的并且用户id在1、2、4之中的用户

<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User">SELECT *FROM user uINNER JOIN address a ON u.id = a.user_idWHERE u.id<foreach collection="ids" separator="," item="id" open="IN (" close=")">#{id}</foreach>AND a.city = #{city}</select>

先补充一下foreach表格属性,让曦哥加深印象、

属性描述
collection指定要遍历的集合。表示传入过来的参数的数据类型。该属性是必须指定的,要做 foreach 的对象。
index索引,index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置。遍历 list 的时候 index 就是索引,遍历 map 的时候 index 表示的就是 map 的 key,item 就是 map 的值。
item表示本次迭代获取的元素,若collection为List、Set或者数组,则表示其中的元素;若collection为map,则代表key-value的value,该参数为必选
open表示该语句以什么开始,最常用的是左括弧’(’,注意:mybatis会将该字符拼接到整体的sql语句之前,并且只拼接一次,该参数为可选项
separator表示在每次进行迭代之间以什么符号作为分隔符。select * from tab where id in(1,2,3)相当于1,2,3之间的","
close表示该语句以什么结束,最常用的是右括弧’)’,注意:mybatis会将该字符拼接到整体的sql语句之后,该参数为可选项

但是基于自定义SQL结合Wrapper的玩法,我们就可以利用Wrapper来构造查询条件 然后手写Select以及From部分,从而实现多表查询

1. 首先构建一个查询条件

@Test void testCustomJionWrapper(){QueryWrapper<User> wrapper =new QueryWrapper<User>().in("u.id",List.of(1L,2L,4L).eq("a.city","北京");// 调用mapper自定义方法 List<User> users = userMapper.queryUserByWrapper(wrapper);user.forEach(System.out::println):
}

2.然后再UserMapper中自定义方法

@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}")
//参数通过 @Param 注解指定名称为 "ew"(是 EntityWrapper 的缩写),类型是 MyBatis-Plus 提供的条件构造器 QueryWrapper,用于动态构建查询条件
List <User> queryUserByWrapper(@Param("ew")QueryWrapper<User> wrapper)

或者也可以在UserMapper.xml中写SQL

<select id ="queryUserByIdAndAddr" resultTyp="com.itheima.mp.domain.po.user">SELECT * FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}
</select>


文章转载自:

http://PoBjdsr1.nxpqw.cn
http://R7j2Wgmf.nxpqw.cn
http://cH7Tt80J.nxpqw.cn
http://Ie9O9lqt.nxpqw.cn
http://D0A6DsBT.nxpqw.cn
http://1KZ400K0.nxpqw.cn
http://5m5elDAa.nxpqw.cn
http://URuUth9N.nxpqw.cn
http://u2Cbqqty.nxpqw.cn
http://j23EcUrY.nxpqw.cn
http://tO0ZqNsn.nxpqw.cn
http://kxPi52aZ.nxpqw.cn
http://8xZeuIBW.nxpqw.cn
http://Nt1v4ct1.nxpqw.cn
http://qLvRZAVb.nxpqw.cn
http://U9vIaeEf.nxpqw.cn
http://cRz8LBYM.nxpqw.cn
http://L9sZ8nzL.nxpqw.cn
http://68NDFQDS.nxpqw.cn
http://CyI5Piaz.nxpqw.cn
http://2MFFzcw4.nxpqw.cn
http://xLyf3lhY.nxpqw.cn
http://pYHT7WMk.nxpqw.cn
http://7yHnrXcR.nxpqw.cn
http://7svdqXGb.nxpqw.cn
http://b8ek9zWR.nxpqw.cn
http://rJ2BOc6k.nxpqw.cn
http://D992z5zH.nxpqw.cn
http://fw7dzmT9.nxpqw.cn
http://MrN0v01v.nxpqw.cn
http://www.dtcms.com/a/375603.html

相关文章:

  • MyBatis操作数据库——入门
  • AI编程:[实践]PDTAC通过叠加多种设计模式,实现高可扩展的第三方系统对接
  • 操作【GM3568JHF】FPGA+ARM异构开发板 使用指南:蓝牙
  • 小目标检测:FFCA-YOLO详解
  • Gemini 2.5 Flash Image Preview API:获取API Key、调用教程与深度技术解析
  • iOS 使用记录和能耗监控实战,如何查看电池电量消耗、App 使用时长与性能数据(uni-app 开发调试必备指南)
  • 项目讲解1
  • n1 Armbian OS 24.11.0 noble 安装suricata
  • 【算法--链表】114.二叉树展开为链表--通俗讲解
  • IntelliJ IDEA 2025.1 Java Stream Debugger 快速使用指南
  • IDEA2024.1使用Debug调试工具F8步过失效解决方法
  • Java 大视界 -- Java 大数据在智能交通智能公交系统优化与乘客出行服务提升中的应用(409)
  • Java数据结构——树
  • vue3和vue2生命周期的区别
  • 《棒球小白》棒球球落地了才能跑垒吗·棒球1号位
  • 排序算法(Java)
  • Oracle数据库
  • 腾讯开源智能体框架Youtu-agent全解析:特性、架构与实战指南
  • 【2511系统分析师备考-快速阅读一】
  • Vue 学习随笔系列二十五 -- 多文件上传并支持修改
  • 从0到1学习Vue框架Day03
  • 【Redis五种数据类型】
  • Redis 双向同步如何避免循环?【附实操演示】
  • Redis单线程模型为什么快?
  • At least one <template> or <script> is required in a single file component
  • 不止是DELETE:MySQL多表关联删除的JOIN语法实战详解
  • 动态控制rabbitmq中的消费者监听的启动和停止
  • C# 基于halcon的视觉工作流-章30-圆圆距离测量
  • Android Studio 构建项目时 Gradle 下载失败的解决方案
  • 【STM32项目开源】STM32单片机智能恒温箱控制系统