Mybatis 进阶 / Mybatis—Puls (详细)

目录

一.动态SQL

1.1标签

[1.2 标签](#1.2 标签)

1.3标签

1.4标签

1.5标签

1.6标签

mybatis总结:

二.Mybatis-Puls

2.1准备工作

2.2CRUD单元测试

2.2.1创建UserInfo实体类

2.2.2编写Mapper接⼝类

[2.2.3 测试类](#2.2.3 测试类)

[2.3 常见注解](#2.3 常见注解)

2.3.1@TableName

2.3.2@TableField

2.4打印日志

2.5条件构造器

2.5.1QueryWrapper

查询操作

更新

删除

2.5.2UpdateWrapper

2.5.3LambdaQueryWrapper

[2.5.4 LambdaUpdateWrapper](#2.5.4 LambdaUpdateWrapper)

2.6⾃定义SQL

示例1:

[示例二 XML的⽅式完成](#示例二 XML的⽅式完成)

示例三:使用注解的方式

MyBatis-Plus总结:


可以先回顾一下初识Mybatis

一.动态SQL

动态 SQL 是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接可以

参考官方文档:MyBatis动态sql

熟悉使用各种标签

1.1<if>标签

在注册信息的时候,可能会遇到这种问题,如图:

注册分为两种字段:必填字段和⾮必填字段,那如果在添加⽤⼾的时候有不确定的字段传⼊,程序应 该如何实现呢?
这个时候就需要使⽤动态标签 来判断了,⽐如添加的时候性别 gender 为⾮必填字段,具体实现如 下

Mapper接⼝定义:

java 复制代码
@Mapper
public interface UserInfoXmlMapper {

    Integer insertUserByCondition(UserInfo userInfo);

}

Mapper.xml实现:

java 复制代码
<?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.example.mybatis.mapper.UserInfoXmlMapper">
    <insert id="insertUserByCondition">
         INSERT INTO user_info(
         username,
         `password`,
         age,
         <if test="gender != null">
             gender,
         </if>
         phone)
         VALUES (
         #{username},
         #{age},
         <if test="gender != null">
             #{gender},
         </if>
         #{phone})
    </insert>
</mapper>

注解⽅式(不推荐)
把上⾯SQL(包括标签), 使⽤ <script></script> 标签括起来就可以

java 复制代码
@Insert("<script>" +
     "INSERT INTO userinfo (username,`password`,age," +
     "<if test='gender!=null'>gender,</if>" +
     "phone)" +
     "VALUES(#{username},#{age}," +
     "<if test='gender!=null'>#{gender},</if>" +
     "#{phone})"+
     "</script>")
Integer insertUserByCondition(UserInfo userInfo);

注意 test 中的 gender,是传⼊对象中的属性,不是数据库字段
问: 可不可以不进⾏判断, 直接把字段设置为null呢?
答: 不可以, 这种情况下, 如果gender字段有默认值, 就会设置为默认值

测试代码:

java 复制代码
@Test
    void insertUserByCondition() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("cuihua");
        userInfo.setPassword("cuihua");
        userInfo.setAge(23);
        userInfo.setPhone("11111111111");
        System.out.println(userInfoXmlMapper.insertUserByCondition(userInfo));
    }

测试结果:

1.2<trim> 标签

之前的插⼊⽤⼾功能,只是有⼀个 gender 字段可能是选填项,如果有多个字段,⼀般考虑使⽤标签结 合标签,对多个字段都采取动态⽣成的⽅式。
标签中有如下属性:

  • prefix:表⽰整个语句块,以prefix的值作为前缀
  • suffix:表⽰整个语句块,以suffix的值作为后缀
  • prefixOverrides:表⽰整个语句块要去除掉的前缀
  • suffixOverrides:表⽰整个语句块要去除掉的后缀

调整后的.XML代码:

java 复制代码
<insert id="insertUserByCondition">
        INSERT INTO user_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username !=null">
                username,
            </if>
            <if test="password !=null">
                `password`,
            </if>
            <if test="age != null">
                age,
            </if>
            <if test="gender != null">
                gender,
            </if>
            <if test="phone != null">
                phone,
            </if>
        </trim>
        VALUES
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username !=null">
                #{username},
            </if>
            <if test="password !=null">
                #{password},
            </if>
            <if test="age != null">
                #{age},
            </if>
            <if test="gender != null">
                #{gender},
            </if>
            <if test="phone != null">
                #{phone}
            </if>
        </trim>
    </insert>

使⽤注解⽅式(不推荐)

java 复制代码
 @Insert("<script>" +
            "INSERT INTO user_info " +
            "<trim prefix='(' suffix=')' suffixOverrides=','>" +
            "<if test='username!=null'>username,</if>" +
            "<if test='password!=null'>password,</if>" +
            "<if test='age!=null'>age,</if>" +
            "<if test='gender!=null'>gender,</if>" +
            "<if test='phone!=null'>phone,</if>" +
            "</trim>" +
            "VALUES " +
            "<trim prefix='(' suffix=')' suffixOverrides=','>" +
            "<if test='username!=null'>#{username},</if>" +
            "<if test='password!=null'>#{password},</if>" +
            "<if test='age!=null'>#{age},</if>" +
            "<if test='gender!=null'>#{gender},</if>" +
            "<if test='phone!=null'>#{phone}</if>" +
            "</trim>"+
            "</script>")
    Integer insertUserByCondition1(UserInfo userInfo);

在以上 sql 动态解析时,会将第⼀个 部分做如下处理:

  • 基于 prefix 配置,开始部分加上 (
  • 基于 suffix 配置,结束部分加上 )
  • 多个 组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于 suffixOverrides 配置去掉最后⼀个 ,
  • 注意 <if test="username !=null"> 中的 username 是传⼊对象的属性

1.3<where>标签

需求: 传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为 null 的,都为查询条件. 例如 username 为 "a",则查询条件为 where username="a"
Mapper接口代码:

java 复制代码
@Mapper
public interface UserInfoXmlMapper {

    List<UserInfo> selecetByCondition(UserInfo userInfo);
}

.XML代码实现:

java 复制代码
  <select id="selecetByCondition" resultType="com.example.mybatis.model.UserInfo">
        select * from user_info
        <where>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="password != null">
                password = #{password}
            </if>
        </where>
    </select>

<where> 只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或 OR

测试代码:

查询条件我只写了一个,可以写多个的

java 复制代码
 @Test
    void selecetByCondition() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("wangwu");
        System.out.println(userInfoXmlMapper.selecetByCondition(userInfo));
    }

测试结果:

1.4<set>标签

需求: 根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容
接⼝定义: 根据传⼊的⽤⼾ id 属性,修改其他不为 null 的属性

java 复制代码
@Mapper
public interface UserInfoXmlMapper {

    Integer updateByCondition(UserInfo userInfo);
}

.XML代码实现:

java 复制代码
<update id="updateByCondition">
        update user_info
        <set>
          <if test="username != null" >
              username = #{username},
          </if>
          <if test="password != null" >
              password = #{password},
          </if>
          <if test="age != null" >
              age = #{age}
          </if>
        </set>
        where id = #{id}
    </update>

测试代码:

目的把ID为 '1' 的名字改为 "tietui" ,并打印

java 复制代码
   @Test
    void updateByCondition() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("tietui");
        userInfo.setId(1);
        System.out.println(userInfoXmlMapper.updateByCondition(userInfo));
    }

测试结果:


<set> :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号. (⽤于update语句中)

1.5<foreach>标签

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:

  • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串

需求目的: 根据多个userid, 删除⽤⼾数据

接口方法实现:

java 复制代码
@Mapper
public interface UserInfoXmlMapper {

    Integer delete(List<Integer> list);
}

.XML代码实现:

java 复制代码
    <delete id="delete">
        delete from user_info
        where id in
        <foreach collection="list" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

测试代码:

java 复制代码
    @Test
    void Delete() {
        List<Integer> list =new ArrayList<>();
        list.add(5);
        list.add(8);
        System.out.println(userInfoXmlMapper.delete(list));
    }

测试结果:

1.6<include>标签

就是直接对需要的代码进⾏抽取,将其通过 <sql> 标签封装到⼀个SQL⽚段,然后再通过 <include> 标签进⾏引⽤

  • <sql> :定义可重⽤的SQL⽚段
  • <include> :通过属性refid,指定包含的SQL⽚段
    例如:
    可能会多次使用这个sql片段 ,就可以加入<sql>标签完成复用
java 复制代码
<sql id="allColumn">
 id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

通过 <include> 标签在原来抽取的地⽅进⾏引⽤。操作如下:

java 复制代码
 <select id="queryById" resultType="com.example.mybatis.model.UserInfo">
        select
        <include refid="allColumn"></include>
        from userinfo where id= #{id}
 </select>

mybatis总结:

  • 学习了MyBatis动态SQL的⼀些标签使⽤. <if>标签中, 使⽤的是Java对象的属性, ⽽⾮数据库字段.
  • 动态SQL的实现, 注解和xml的实现⽅式相似, 区别是注解⽅式需要添加 <script></script> .
  • 但是使⽤注解的⽅式时, Idea不会进⾏格式检测, 容易出错, 建议使⽤xml的⽅式

二.Mybatis-Puls

MyBatis-Plus(简称 MP) 是⼀个 MyBatis 的增强⼯具, 在 MyBatis 的基础上只做增强不做改变, 为简化开 发. 提⾼效率⽽⽣

特性:

  • 润物⽆声: 只做增强不做改变,引⼊它不会对现有⼯程产⽣影响,如丝般顺滑.
  • 效率⾄上: 只需简单配置,即可快速进⾏单表 CRUD 操作,从⽽节省⼤量时间.
  • 丰富功能: 代码⽣成、⾃动分⻚、逻辑删除、⾃动填充、拦截器等功能⼀应俱全.
  • ⼴泛认可: 连续 5 年获得开源中国年度最佳开源项⽬殊荣,Github 累计 16K Star.

⽀持数据库:

PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, OceanBase, H2, DB2...
(任何能使⽤ MyBatis 进⾏增删改查,并且⽀持标准 SQL 的数据库应该都在 MyBatis-Plus 的⽀持范围内)

官方网址:MyBatis-Puls 为简化开发而生

Mybatis-Plus操作数据库的步骤:

  1. 准备⼯作(数据准备, 项⽬准备, 引⼊依赖, 配置数据库连接信息)
  2. 编码(数据库表对应的实体类, 以及数据操作的Mapper⽂件)
  3. 测试

2.1准备工作

创建数据库 ➡️ 创建表(例如用户表) ➡️ 创建对应的实体类User

与Mybatis一样:

  • 创建springboot项目
  • 添加MyBatis-Plus和MySQL依赖, 配置数据库连接信息

添加 MyBatis-Plusy依赖

java 复制代码
    <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.9</version>
    </dependency>

添加 MySQL依赖

java 复制代码
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

.yml文件配置:

java 复制代码
# 数据库连接配置
spring:
  datasource:
    #数据库连接的url
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    #连接数据库的⽤⼾名
    username: root
    #连接数据库的⽤⼾名
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
    mapper-locations: classpath:mybatis/**Mapper.xml
  # 配置打印 MyBatis日志
    configuration:
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      map-underscore-to-camel-case: true #配置驼峰⾃动转换

2.2CRUD单元测试

2.2.1创建UserInfo实体类

实体类的属性名与表中的字段名一一对应

java 复制代码
package com.example.mybatisplus.mode;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

@Data
@TableName("user_info")
public class UserInfo {
    @TableId
    private Integer id;
    @TableField("username")
    private String username ;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2.2.2编写Mapper接⼝类

MybatisPlus提供了⼀个基础的 BaseMapper 接⼝,已经实现了单表的CRUD, 我们⾃定义的
Mapper只需要继承这个BaseMapper, 就⽆需⾃⼰实现单表CRUD了

java 复制代码
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

}

也可以在启动类上添加 @MapperScan , 扫描Mapper⽂件夹, ⼆选⼀即可.

2.2.3 测试类

在创建出来的SpringBoot⼯程中,在src下的test⽬录下,已经⾃动帮我们创建好了测试类 ,我们可以 直接使⽤这个测试类来进⾏测试

测试基本的CRUD功能 :

java 复制代码
package com.example.mybatisplus;

import com.example.mybatisplus.mapper.UserInfoMapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {
    @Autowired
    UserInfoMapper userInfoMapper;
    @Test
    void contextLoads() {
        System.out.println(userInfoMapper.selectById(1));
    }
    @Test
    void testInsert() {
        UserInfo user = new UserInfo();
        user.setUsername("bite");
        user.setPassword("123456");
        user.setAge(11);
        user.setGender(0);
        user.setPhone("18610001234");
        userInfoMapper.insert(user);
    }
    @Test
    void testSelectById() {
        UserInfo user = userInfoMapper.selectById(1L);
        System.out.println("user: " + user);
    }
    @Test
    void testSelectByIds() {
        List<UserInfo> users = userInfoMapper.selectBatchIds(List.of(1L, 2L, 3L,
                4L));
        users.forEach(System.out::println);
    }
    @Test
    void testUpdateById() {
        UserInfo user = new UserInfo();
        user.setId(1);
        user.setPassword("4444444");
        userInfoMapper.updateById(user);
    }
}

2.3 常见注解

在上⾯的程序中, MyBatis是如何知道, 我们要操作的是哪张表, 表⾥有哪些字段呢?
看下咱们Mapper的代码:

java 复制代码
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

}

UserInfoMapper 在继承 BaseMapper 时, 指定了⼀个泛型, 这个UserInfo就是与数据库表相对应的实体类.
MyBatis-Plus会根据这个实体类来推断表的信息.
默认情况下:

  1. 表名: 实体类的驼峰表⽰法转换成蛇形表⽰法(下划线分割), 作为表名. ⽐如UserInfo -> user_info
  2. 字段: 根据实体类的属性名 转换为蛇形表⽰法作为字段名. ⽐如deleteFlag -> delete_flag
  3. 主键: 默认为id

2.3.1@TableName

修改实体类名UserInfo为 Userinfo
运⾏结果:

从⽇志可以看到, 默认查找的表名为userinfo
可以通过 @TableName 来标识实体类对应的表

java 复制代码
@Data
@TableName("user_info")
public class UserInfo {
    @TableId
    private Integer id;
    private String username ;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    @TableField("delete_flag")
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2.3.2@TableField

修改属性名 deleteFlag 为 deleteflag
运⾏结果:

⽇志可以看到, 根据属性名转换前的字段名为: deleteflag
可以通过 @TableField 来标识 对应的字段名

java 复制代码
@Data
@TableName("user_info")
public class UserInfo {
    @TableId
    private Integer id;
    private String username ;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    @TableField("delete_flag")
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2.3.3 @TableId

修改属性名 id 为 userId

运⾏结果:

可以通过 @TableId 来 指定对应的主键

java 复制代码
@Data
@TableName("user_info")
public class UserInfo {
    @TableId
    private Integer id;
    private String username ;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    @TableField("delete_flag")
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

如果属性名和字段名不⼀致, 需要在 @TableId 指明对应的字段名
属性名和字段⼀致的情况下, 直接加 @TableId 注解就可以.

2.4打印日志

添加文件配置即可

java 复制代码
mybatis-plus:
  # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
    mapper-locations: classpath:mybatis/**Mapper.xml
  # 配置打印 MyBatis日志
    configuration:
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      map-underscore-to-camel-case: true #配置驼峰⾃动转换

2.5条件构造器

⼊⻔程序⾥的使⽤, 都是简单的CRUD, 在实际的应⽤场景中, 我们还需要使⽤更复杂的操作, MyBatisPlus 也给我们提供了相应的⽀持.

MyBatis-Plus 提供了⼀套强⼤的条件构造器(Wrapper), ⽤于构建复杂的数据库查询条件. Wrapper 类允许开发者以链式调⽤的⽅式构造查询条件, ⽆需编写繁琐的 SQL 语句, 从⽽提⾼开发效率并减少 SQL 注⼊的⻛险

以下是主要的 Wrapper 类及其功能:

  • AbstractWrapper:这是⼀个抽象基类, 提供了所有 Wrapper 类共有的⽅法和属性. 详细参考官⽹ 介绍: 条件构造器
  • QueryWrapper:⽤于构造查询条件, 在AbstractWrapper的基础上拓展了⼀个select⽅法, 允许指 定查询字段.
  • UpdateWrapper: ⽤于构造更新条件, 可以在更新数据时指定条件.
  • LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器, 它通过 Lambda 表达式来引⽤ 实体类的属性,从⽽避免了硬编码字段名.
  • LambdaUpdateWrapper: 基于 Lambda 表达式的更新条件构造器, 它允许你使⽤ Lambda 表达 式来指定更新字段和条件,同样避免了硬编码字段名的问题

2.5.1QueryWrapper

QueryWrapper并不只⽤于查询语句, ⽆论是修改, 删除, 查询, 都可以使⽤QueryWrapper来构建查询条件.

查询操作

完成下述SQL查询:

java 复制代码
SELECT id,username,password,age FROM user_info WHERE age = 18 AND username 
"%min%"

测试代码:

java 复制代码
  @Test
    void testQueryWrapper(){
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
                .select("id","username","password","age")
                .eq("age",18)
                .like("username", "min");
        List<UserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);
        userInfos.forEach(System.out::println);
    }

注意:

默认情况下Mybatis-Plus会根据 @TableFiled ⽣成别名, 当指定了QueryWrapper的select属性后
就仅仅是属性值⽽没有了别名. 查询出来的结果会对应不上

解决办法:

  1. ⾃⼰写⾃定义SQL
  2. 实体类名和字段名保持⼀致
  3. 不指定QueryWrapper的select字段
  4. 使⽤LambdaQueryWrapper实现
更新

完成下述SQL查询操作:

java 复制代码
UPDATE user_info SET delete_flag=? WHERE age < 20

测试代码:

java 复制代码
  @Test
    void testUpdateByQueryWrapper(){
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
                .lt("age", 20);
        UserInfo userInfo = new UserInfo();
        userInfo.setDeleteFlag(1);
        userInfoMapper.update(userInfo, userInfoQueryWrapper);
    }
  • lt : "less than" 的缩写,表⽰⼩于.
  • le : "less than or equal to"的缩写, 表⽰⼩于等于
  • ge : "greater than or equal to" 的缩写, 表⽰⼤于等于.
  • gt : "greater than" 的缩写, 表⽰⼤于.
  • eq : "equals" 的缩写, 表⽰等于.
  • ne : "not equals" 的缩写, 表⽰不等于
删除

完成下述SQL查询

java 复制代码
DELETE FROM user_info WHERE age = 18

测试代码:

java 复制代码
 @Test
    void testDeleteByQueryWrapper(){
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
                .eq("age",18);
        userInfoMapper.delete(userInfoQueryWrapper);
    }

2.5.2UpdateWrapper

对于更新, 我们也可以直接使⽤ UpdateWrapper, 在不创建实体对象的情况下, 直接设置更新字段和条 件.
基础更新:
完成下述SQL查询:

java 复制代码
UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

测试代码:

java 复制代码
 @Test
    void testUpdateByUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
                .set("delete_flag",0)
                .set("age", 5)
                .in("id", List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

基于SQL更新:

完成下述SQL查询:

java 复制代码
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

测试代码:

java 复制代码
 @Test
    void testUpdateBySQLUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
                .setSql("age = age+10")
                .in("id", List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

2.5.3LambdaQueryWrapper

QueryWrapper 和 UpdateWrapper存在⼀个问题, 就是需要写死字段名, 如果字段名发⽣变更, 可能会 因为测试不到位酿成事故.
MyBatis-Plus 给我们提供了⼀种基于Lambda表达式的条件构造器, 它通过 Lambda 表达式来引⽤实体 类的属性,从⽽避免了硬编码字段名, 也提⾼了代码的可读性和可维护性

  • LambdaQueryWrapper
  • LambdaUpdateWrapper

分别对应上述的QueryWrapper和UpdateWrapper
具体使用:

java 复制代码
@Test
    void testLambdaQueryWrapper(){
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
        queryWrapper.lambda()
                .select(UserInfo::getUsername, UserInfo::getPassword,UserInfo::getAge)
                .eq(UserInfo::getUserId, 1);
        userInfoMapper.selectList(queryWrapper).forEach(System.out::println);
    }

2.5.4 LambdaUpdateWrapper

LambdaUpdateWrapper⽤法和 LambdaQueryWrapper相似

java 复制代码
@Test
    void testLambdUpdateByUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
        updateWrapper.lambda()
                .set(UserInfo::getDeleteFlag, 0)
                .set(UserInfo::getAge, 5)
                .in(UserInfo::getUserId, List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

2.6⾃定义SQL

在实际的开发中, MyBatis-Plus提供的操作不能满⾜我们的实际需求, MyBatis-Plus 也提供了⾃定义 SQL的功能, 我们可以利⽤Wrapper构造查询条件, 再结合Mapper编写SQL
要使用自定义SQL的功能 MyBatis-Plus版本号不得低于3.0.7

示例1:

完成下述SQL查询

java 复制代码
select id,username,password,age FROM user_info WHERE username = "admin"

Mappe接口代码:

java 复制代码
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    @Select("select id,username,password,age FROM user_info ${ew.customSqlSegment}")
    List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER)Wrapper<UserInfo> wrapper);
}

测试代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;
    @Test
    void queryUserByCustom() {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("username","admin");
        userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
    }
}

注意事项:

  • 参数命名:在⾃定义 SQL 时, 传递 Wrapper 对象作为参数时, 参数名必须为 ew ,或者使⽤注解 @Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象.
  • 使⽤ ${ew.customSqlSegment} :在 SQL 语句中,使⽤ ${ew.customSqlSegment} 来 引⽤ Wrapper 对象⽣成的 SQL ⽚段.
  • 不⽀持基于 entity 的 where 语句:⾃定义 SQL 时,Wrapper 对象不会基于实体类⾃动⽣成 where ⼦句,你需要⼿动编写完整的 SQL 语句

示例二 XML的⽅式完成

MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变, 所以也⽀持XML的实现⽅式

上述功能也可以使⽤XML的⽅式完成

1.配置mapper路径 :

java 复制代码
mybatis-plus:
 mapper-locations: "classpath*:/mapper/**.xml" # Mapper.xml

2.mapper接口方法:

java 复制代码
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}

3.编写XML:

java 复制代码
<?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.example.mybatisplus.mapper.UserInfoMapper">


    <select id="queryUserByCustom" resultType="com.example.mybatisplus.mode.UserInfo">
         select * from user_info ${ew.customSqlSegment}
    </select>
</mapper>

4.测试

java 复制代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;
    
    @Test
    void queryUserByCustom() {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
                .eq("userName","lisi");
        userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
    }
}

测试结果:

示例三:使用注解的方式

完成下述SQL查询

java 复制代码
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

mapper接口方法:

java 复制代码
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    
    @Update("UPDATE user_info SET age = age+ #{addAge} ${ew.customSqlSegment}")
    void updateUserByCustom(@Param("addAge") int addAge, @Param("ew")Wrapper<UserInfo> wrapper);
}

测试代码:

java 复制代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;
    
    @Test
    void updateUserByCustom() {
        QueryWrapper<UserInfo> queryWrapper =new QueryWrapper<UserInfo>()
                .in("id", List.of(1,2,3));
        //目的把id为1,2,3  在原先年龄的基础上加10
        userInfoMapper.updateUserByCustom(10,queryWrapper);
    }
}

测试结果:

MyBatis-Plus总结:

  • MyBatis-Plus 是 MyBatis 的增强⼯具, 在 MyBatis 的基础上只做增强不做改变, 可以⽤更少的代码实现数据库表的CRUD, 让我们的开发变得更加简单
  • MyBatis-Plus ⽀持⾃定义SQL, 版本不低于3.0.7, 传递 Wrapper 对象作为参数时, 参数名必须为 ew,在 SQL 语句中,使⽤ ${ew.customSqlSegment} 来引⽤ Wrapper 对象⽣成的 SQL ⽚段
相关推荐
小菜日记^_^8 小时前
苍穹外卖项目总结(二)
java·spring boot·spring·tomcat·maven·mybatis·postman
阑梦清川8 小时前
用户中心项目教程(五)---MyBatis-Plus完成后端初始化+测试方法
java·数据库·mybatis
灰色孤星A9 小时前
MyBatisPlus详解(三)lambdaQuery、lambdaUpdate、批量新增、代码生成、Db静态工具、逻辑删除
java·mybatis·mybatisplus·代码生成器·逻辑删除·lambdaquery
violin-wang1 天前
XML映射文件
xml·java·前端·mybatis
媤纹琴獣1 天前
mybatis xml sql
xml·sql·mybatis
->yjy1 天前
封装Redis工具类
java·redis·mybatis
计算机学姐2 天前
基于SpringBoot的健身房管理系统
java·vue.js·spring boot·后端·mysql·spring·mybatis
爱上语文2 天前
MyBatis实现数据库的CRUD
java·开发语言·数据库·mybatis
青木川崎2 天前
Mybatis面试题
java·开发语言·mybatis