一.自定义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>
使用$进行条件拼接。
测试通过:

总结
