mybatisplus的使用

xiaojiuaigc@163.com 发布于 2025-05-05 88 次阅读


MyBataisPlus

Mybatis-Plus(简称MP)是一个基于Mybatis框架增强工具,它在Mybatis的基础上只做增强而不做改变,旨在简化开发、提高效率。Mybatis-Plus提供了一系列的功能和特性,使得开发人员能够更加高效地使用Mybatis进行数据库操作。

官网地址:https://mybatis.plus/

使用方式

1.引入依赖

<!– mybatis-plus 的起步依赖 –>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.7</version>
</dependency>

在引导类上加入注解,配置要自动扫描的Mapper

 

mapper类继承BaseMapper<>就可以使用了

配置文件

mybatis-plus:
  type-aliases-package: com.itheima.pojo # 配置MyBatis的别名包
  mapper-locations: classpath:mapper/**/*Mapper.xml # 配置MyBatis的mapper文件位置
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰命名
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 配置MyBatis的日志输出
  global-config:
    db-config:
      id-type: auto             # 全局id类型为自增长
      update-strategy: not_null # 更新策略:只更新非空字段

各层所要加的东西

Service

extends IService<数据库表对应的实体类名字>

ServiceImpl

extends ServiceImpl<EmpMapper, Emp> implements EmpService

Mapper

 extends BaseMapper<数据库表对应的实体类名字>

常见注解

@TableName

  • 描述:表名注解,标识实体类对应的表
  • 使用位置:实体类
  • 示例:

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
    private Long id;

    private String name;

    private Boolean isMarried;

    private Integer order;

    private String address;
}

@TableId

  • 描述:主键注解,标识实体类中的主键字段
  • 使用位置:实体类的主键字段
  • 示例

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
    @TableId(value = “id”, type = IdType.AUTO)
    private Long id;

    private String name;

    private Boolean isMarried;

    private Integer order;

    private String address;
}

  • 注解支持两个属性:

属性

类型

必须指定

默认值

描述

value

String

“”

字段描述

type

Enum

IdType.NONE

指定主键类型

IdType支持的类型有:

描述

AUTO

数据库 ID 自增

NONE

无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)

INPUT

insert 前自行 set 主键值

ASSIGN_ID

分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)

ASSIGN_UUID

分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法)

ID_WORKER

分布式全局唯一 ID 长整型类型(please use ASSIGN_ID)

UUID

32 位 UUID 字符串(please use ASSIGN_UUID)

ID_WORKER_STR

分布式全局唯一 ID 字符串类型(please use ASSIGN_ID)

这里比较常见的有三种:

  • AUTO:利用数据库的id自增长
  • INPUT:手动生成id
  • ASSIGN_ID:雪花算法生成Long类型的全局唯一id,这是默认的ID策略

@TableField

  • 普通字段注解
  • 示例

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
    @TableId(value = “id”, type = IdType.AUTO)
    private Long id;

    @TableField(“username”)
    private String name;

    @TableField(“is_married”)
    private Boolean isMarried;

    @TableField(“`order`”)
    private Integer order;

    @TableField(exist = false)
    private String address;
}

一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:

  • 成员变量名与数据库字段名不一致
  • 成员变量是以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。
  • 成员变量名与数据库一致,但是与数据库的关键字冲突。使用@TableField注解给字段名添加转义字符:“
  • 成员变量不是数据库中的字段,则需要使用exist表明为false

核心功能

MyBatais主要有三个核心功能:条件构造器、自定义SQL、Service接口

条件构造器

除了新增以外,查询、修改、删除的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外,还支持更加复杂的where条件。

 

 参数中的Wrapper就是条件构造的抽象类,其下有很多默认实现,继承关系如图:

 

Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法:

 

 而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法,允许指定查询字段:

 

 而UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法,允许指定SQL中的SET部分:

 

接下来,我们就来看看如何利用Wrapper实现复杂查询。

QueryWrapper

无论是修改、删除、查询,都可以使用QueryWrapper来构建查询条件。接下来看一些例子: 查询查询姓名中包含且薪资大于等于5000的员工的 id, name, phone, salary字段。代码如下:

首先让EmpMapper继承自BaseMapper:

@Mapper
public interface EmpMapper extends BaseMapper<Emp> {

}

为了方便测试,咱们使用单元测试学习QueryWrapper的使用:

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
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
public class TestQueryWrapper {

    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testQueryWrapper() {
        // 查询姓名中包含“李”且薪资大于等于5000的员工的 id, name, phone, salary字段
        QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(“name”, “李”)
                .ge(“salary”, 5000)
                .select(“id”, “name”, “phone”, “salary”);

        List<Emp> emps = empMapper.selectList(queryWrapper);
        emps.forEach(System.out::println);
    }
}

更新更新名为”李忠”的员工的薪水为18000,代码如下:

@Test
public void testUpdateByQueryWrapper() {
    // 更新名为”李忠”的员工的薪水为18000
    Emp emp = new Emp();
    emp.setSalary(18000);
    QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq(“name”, “李忠”);
    empMapper.update(emp, queryWrapper);
}

UpdateWrapper

更新:更新id为5, 6, 7的员工的薪水,加2000,代码如下:

update emp set salary = salary + 2000 where id in (5, 6, 7);

@Test
public void testUpdateWrapper() {
    // 更新id为5, 6, 7的员工的薪水,加2000
    UpdateWrapper<Emp> updateWrapper = new UpdateWrapper<>();
    updateWrapper.in(“id”, 5, 6, 7)
            .setSql(“salary = salary + 2000”);
    empMapper.update(updateWrapper);
}

LambdaQueryWrapper

无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称,这在编程规范中显然是不推荐的。 那怎么样才能不写字段名,又能知道字段名呢?

其中一种办法是基于变量的gettter方法结合反射技术来实现,因此我们只要将条件对应的字段的getter方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含两个:

  • LambdaQueryWrapper
  • LambdaUpdateWrapper

分别对应QueryWrapper和UpdateWrapper

其使用方式如下:

@Test
public void testLambdaUpdateWrapper() {
    // 更新id为5, 6, 7的员工的薪水,加2000
    LambdaUpdateWrapper<Emp> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.in(Emp::getId, 5, 6, 7)
            .setSql(“salary = salary + 2000”);
    empMapper.update(updateWrapper);
}

自定义SQL

在开发时需要遵守开发规范,不能将SQL写在Service中可以将条件放入service中然后在Mapper中用条件进行拼接

 List<Long> ids = List.of(5L, 6L, 7L);
        int amount = 2000;
        //构建修改条件
        LambdaQueryWrapper<Emp> wrapper=new LambdaQueryWrapper<Emp>().in(Emp::getId,ids);
        //自定义SQL方法调用
        this.empMapper.updateBalanceByIds(wrapper,amount);

void updateBalanceByIds(@Param(“ew”) LambdaQueryWrapper<Emp> wrapper,@Param(“amount”) int amount);

 <update id=”updateBalanceByIds”>
        update emp set salary =salary -#{amount} ${ew.customSqlSegment}
    </update>

Service接口

MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。 通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类:

  • save:新增
  • remove:删除
  • update:更新
  • get:查询单个结果
  • list:查询集合结果
  • count:计数
  • page:分页查询
基本的增删改查

我们先来看下基本的CRUD接口,新增

 

  • save是新增单个元素
  • saveBatch是批量新增
  • saveOrUpdate是根据id判断,如果数据存在就更新,不存在则新增
  • saveOrUpdateBatch是批量的新增或修改

删除:

 

  • removeById:根据id删除
  • removeByIds:根据id批量删除
  • removeByMap:根据Map中的键值对为条件删除
  • remove(Wrapper<T>):根据Wrapper条件删除
  • ~~removeBatchByIds~~:暂不支持

修改:

 

  • updateById:根据id修改
  • update(Wrapper<T>):根据UpdateWrapper修改,Wrapper中包含set和where部分
  • update(T,Wrapper<T>):按照T内的数据修改与Wrapper匹配到的数据
  • updateBatchById:根据id批量修改

Get:

 

  • getById:根据id查询1条数据
  • getOne(Wrapper<T>):根据Wrapper查询1条数据
  • getBaseMapper:获取Service内的BaseMapper实现,某些时候需要直接调用Mapper内的自定义SQL时可以用这个方法获取到Mapper

List:

 

  • listByIds:根据id批量查询
  • list(Wrapper<T>):根据Wrapper条件查询多条数据
  • list():查询所有

Count

 

  • count():统计所有数量
  • count(Wrapper<T>):统计符合Wrapper条件的数据数量