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

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

java 复制代码
@Test
void testUpadateWrapper(){
   List<Long> ids = List.of(1L,2L,4L);
   //生成SQL
   UpadateWrapper<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

java 复制代码
@Test
void testCustomWrapper() {
    // 1.准备自定义查询条件
    List<Long> ids = List.of(1L, 2L, 4L);
    QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);

    // 2.调用mapper的自定义方法,直接传递Wrapper
    userMapper.deductBalanceByIds(200, wrapper);
}

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

java 复制代码
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 中用于集成条件构造器(QueryWrapperLambdaQueryWrapper)的核心占位符,主要作用是

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之中的用户

XML 复制代码
<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User">
      SELECT *
      FROM user u
      INNER JOIN address a ON u.id = a.user_id
      WHERE 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. 首先构建一个查询条件
java 复制代码
@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中自定义方法

java 复制代码
@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

java 复制代码
<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>
相关推荐
ChineHe14 小时前
Redis数据类型篇002_详解Strings核心命令与存储结构
数据库·redis·缓存
清水白石00814 小时前
《从零到进阶:Pydantic v1 与 v2 的核心差异与零成本校验实现原理》
数据库·python
电商API&Tina14 小时前
京东 API 数据采集接口接入与行业分析
运维·服务器·网络·数据库·django·php
柠檬叶子C15 小时前
PostgreSQL 忘记 postgres 密码怎么办?(已解决)
数据库·postgresql
864记忆15 小时前
Qt创建连接注意事项
数据库·qt·nginx
毕设十刻16 小时前
基于Vue的迅读网上书城22f4d(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
薛定谔的猫198216 小时前
Langchain(十二)LangGraph 实战入门:用流程图思维构建 LLM 工作流
数据库·microsoft
坐吃山猪17 小时前
ChromaDB02-代码实战
数据库·向量数据库·chromadb
摇滚侠17 小时前
MySQL 中 utf8mb4 字符集,字母a占几个字节,一个汉字占几个字节 / MySQL 中 utf8mb3 字符集,字母a占几个字节,一个汉字占几个字节
数据库·mysql
ChineHe17 小时前
Redis数据类型篇001_数据类型梳理与选择指南
数据库·redis·缓存