MybatisPlus-06.核心功能-自定义SQL

一.自定义SQL

MP这么方便了,为什么还要使用自定义SQL?那是因为直接使用MP会在service层写SQL语句,这是不符合开发规范的。

所谓自定义SQL即:

下面我们来看两个案例来理解:

1.将id在指定范围的用户(例如1、2、4)的余额扣减指定值 这种sql语句使用mp编写起来很简单,如下:

我们使用springboot三层架构编写时,是要将这部分代码编写到service层中的。这就相当于我们直接将sql语句写在了service层当中,这在许多企业开发规范中是不允许的。要求sql语句必须写在mapper层。

但是放弃mp去纯手写太复杂,mp擅长写复杂where条件,前面的部分mp也能写。但是在有些场景下mp就写不了前面的语句了。因此我们选择前面使用sql语句。后面使用mp写。

这种使用count聚合函数并且还起别名的mp也没办法实现。因此使用自定义sql。

使用mp构造复杂where语句,前面的sql语句手写,然后拼起来。当然我们不是在service层去拼,而是将mp构造的条件传递到mapper层。在mapper或xml中组装。

后面直接使用$符号将wrapper条件拼接上去,名称为ew.customSqlSegment。

二.代码实现

sql 复制代码
@Test
    void testCustomSqlUpdate() {
        // 将用户id为1,2,4的用户余额减200
        List<Long> ids = List.of(1L,2L,4L);
        int amount = 200;
        // 1.构造Wrapper来定义where语句
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>()
                .in("id",ids);
        userMapper.updateBalance(queryWrapper,amount);
    }

Mapper层

java 复制代码
package com.itheima.mp.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper extends BaseMapper<User> {

    void updateBalance(@Param("ew") QueryWrapper<User> queryWrapper, @Param("amount") int amount);
//
//    void saveUser(User user);
//
//    void deleteUser(Long id);
//
//    void updateUser(User user);
//
//    User queryUserById(@Param("id") Long id);
//
//    List<User> queryUserByIds(@Param("ids") List<Long> ids);
}

XML文件

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">
<!--    <insert id="saveUser" parameterType="com.itheima.mp.domain.po.User">-->
<!--        INSERT INTO `user` (`id`, `username`, `password`, `phone`, `info`, `balance`)-->
<!--        VALUES-->
<!--        (#{id}, #{username}, #{password}, #{phone}, #{info}, #{balance});-->
<!--    </insert>-->
<!--    <update id="updateUser" parameterType="com.itheima.mp.domain.po.User">-->
<!--        UPDATE `user`-->
<!--        <set>-->
<!--            <if test="username != null">-->
<!--                `username`=#{username}-->
<!--            </if>-->
<!--            <if test="password != null">-->
<!--                `password`=#{password}-->
<!--            </if>-->
<!--            <if test="phone != null">-->
<!--                `phone`=#{phone}-->
<!--            </if>-->
<!--            <if test="info != null">-->
<!--                `info`=#{info}-->
<!--            </if>-->
<!--            <if test="status != null">-->
<!--                `status`=#{status}-->
<!--            </if>-->
<!--            <if test="balance != null">-->
<!--                `balance`=#{balance}-->
<!--            </if>-->
<!--        </set>-->
<!--        WHERE `id`=#{id};-->
<!--    </update>-->
<!--    <delete id="deleteUser" parameterType="com.itheima.mp.domain.po.User">-->
<!--        DELETE FROM user WHERE id = #{id}-->
<!--    </delete>-->

<!--    <select id="queryUserById" resultType="com.itheima.mp.domain.po.User">-->
<!--        SELECT *-->
<!--        FROM user-->
<!--        WHERE id = #{id}-->
<!--    </select>-->

<!--    <select id="queryUserByIds" resultType="com.itheima.mp.domain.po.User">-->
<!--        SELECT *-->
<!--        FROM user-->
<!--        <if test="ids != null">-->
<!--            WHERE id IN-->
<!--            <foreach collection="ids" open="(" close=")" item="id" separator=",">-->
<!--                #{id}-->
<!--            </foreach>-->
<!--        </if>-->
<!--        LIMIT 10-->
<!--    </select>-->

    <update id="updateBalance">
        update tb_user set balance = balance - #{amount} ${ew.customSqlSegment}
    </update>
</mapper>

使用$进行条件拼接。

测试通过:

总结

相关推荐
xuanWb7 小时前
手写一个 LLM API 网关:Anthropic 与 OpenAI 协议转换的完整实现
后端
苍何7 小时前
给 Codex 换皮肤这门生意,被我开源了
后端
用户8356290780517 小时前
Python 实现 Excel 命名范围(Named Range)的创建与管理
后端·python
程序员David7 小时前
我让 Claude 从架构文档一路干到代码,踩了三个坑才摸清边界
后端
Zane19947 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
神奇小汤圆8 小时前
线程池拒绝策略CallerRunsPolicy反而卡死了主线程
后端
神奇小汤圆8 小时前
Jaws:从零构建一个”五脏俱全”的 Java RPC 框架
后端
Csvn8 小时前
📊 SQL 入门 Day 10:递归 CTE — 破解无限层级查询的终极武器
后端·sql
echohelloworld118 小时前
HarmonyOS开发实战:小分享-CreateSelectPage创建分享类型选择器
后端
噢,我明白了8 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel