三、MybatisPlus-进阶使用-自定义sql

198 阅读1分钟

本文是系列文章,目录:
本文是系列文章,目录:
一、MybatisPlus-基本使用
二、MybatisPlus-进阶使用-条件构造器
三、MybatisPlus-进阶使用-自定义sql
四、MybatisPlus-进阶使用-Service接口(1)-基本使用
五、MybatisPlus-进阶使用-Service接口(2)-自定义service
六、MybatisPlus-进阶使用-Service接口(3)- 批量新增
七、MybatisPlus-进阶使用-逻辑删除
八、MybatisPlus-进阶使用-枚举处理器
九、MybatisPlus-进阶使用-JSON类型处理器
十、MybatisPlus-进阶使用-配置文件加密
十一、MybatisPlus-插件功能-分页插件(1)
十二、MybatisPlus-插件功能-分页插件(2)-通用分页封装
十三、MybatisPlus-插件功能-乐观锁插件
十四、MybatisPlus-插件功能-sql性能分析
十五、MybatisPlus-自动填充字段
MybatisPlus-问题汇总

MybatisPlus-进阶使用-自定义sql

正常情况SQL语句最好都维护在持久层,而不是业务层,在前两节案例中,仍然有sql语句出现在业务层,这是不符合规范的。

MybatisPlus提供了自定义SQL功能,可以让我们利用Wrapper生成查询条件,再结合Mapper.xml(也可以是sql注解)编写SQL。

一、基本用法

1.1 测试类

package com.pino.demo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pino.demo.domain.po.User;
import com.pino.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

/**
 * 利用Wrapper生成查询条件,再结合Mapper.xml编写SQL
 */
@SpringBootTest
public class CustomSql {
    @Autowired
    private UserMapper userMapper;

    /**
     *
     */
    @Test
    void testCustomSimpleSql() {
       // 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);
    }
}

1.2 UserMapper

package com.pino.demo.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pino.demo.domain.po.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    /**
     * ew 是wrapper的固定写法
     * @param money
     * @param wrapper
     */
    @Select("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}")
    void deductBalanceByIds(@Param("money") int money, @Param("ew") QueryWrapper<User> wrapper);
}

二、多表关联

理论上来讲MyBatisPlus是不支持多表查询的,不过我们可以利用Wrapper中自定义条件结合自定义SQL来实现多表查询的效果。

基本思想: 把复杂的查询条件换掉,使用warp进行拼接

例如,我们要查询出所有收货地址在北京的并且用户id在1、2、4之中的用户 要是自己基于mybatis实现SQL,大概是这样的:

<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>

可以看出其中最复杂的就是WHERE条件的编写,如果业务复杂一些,这里的SQL会更变态。

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

查询条件这样来构建:

2.1 测试类

@Test
void testCustomJoinWrapper() {
    // 1.准备自定义查询条件
    QueryWrapper<User> wrapper = new QueryWrapper<User>()
            .in("u.id", List.of(1L, 2L, 4L))
            .eq("a.city", "北京");

    // 2.调用mapper的自定义方法
    List<User> users = userMapper.queryUserByWrapper(wrapper);

    users.forEach(System.out::println);
}

2.2 UserMapper.java

@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}")
List<User> queryUserByWrapper(@Param("ew")QueryWrapper<User> wrapper);

当然,也可以在UserMapper.xml中写SQL:

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