MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。使用原生的Mybatis编写持久层逻辑时,所需要的代码是比较繁琐的,需要定义Mapper接口和Mapper.xml文件,每一个方法都需要编写对应的sql语句,会存在很多大量的重复工作,使用MP之后,对通用的方法做了高度的抽取,避免了很多重复工作,可以非常快速的实现了单表的各种增、删、改、查操作。

博客主要讲解Springboot项目下的MybatisPlus框架的核心功能,详细的可参考MP的中文开发文档

入门配置

  • 创建Springboot工程(在IDEA中集成功能)

    • 引入 Spring Boot Starter 父工程:

      1
      2
      3
      4
      5
      <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>3.1.1</version>
      </parent>
    • 引入 spring-boot-starterspring-boot-starter-test依赖:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
        <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      </dependency>

      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      </dependency>

      <!-- web工程也要导入 -->
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
  • 引入mybatis-plus-boot-starter依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
    </dependency>
  • 引入数据库依赖(在IDEA中集成功能)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
    </dependency>

    <!-- 可选 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.18</version>
    </dependency>

快速入门

常用注解

  • @TableName:表名注解,标识实体类对应的表

    1
    2
    3
    4
    5
    6
    7
    @TableName("sys_user")
    public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    }
  • @TableId:主键注释,标识实体类主键字段

    1
    2
    3
    4
    5
    6
    7
    8
    @TableName("sys_user")
    public class User {
    @TableId
    private Long id;
    private String name;
    private Integer age;
    private String email;
    }
    属性 类型 必须指定 默认值 描述
    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 方法)
  • @TableField:字段注解(非主键)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @TableName("sys_user")
    public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    private String email;
    }
    • value:数据库字段名

    • fill:字段自动填充策略

      描述
      DEFAULT 默认不处理
      INSERT 插入时填充字段
      UPDATE 更新时填充字段
      INSERT_UPDATE 插入和更新时填充字段

核心功能

CRUD 接口

Service CRUD 接口

通用 Service CRUD 封装 IService 接口,进一步封装 CRUD 采用 get 查询单行remove 删除list 查询集合page 分页 前缀命名方式区分 Mapper 层避免混淆。

  • Save

    1
    2
    3
    4
    5
    6
    // 插入一条记录(选择字段,策略插入)
    boolean save(T entity);
    // 插入(批量)
    boolean saveBatch(Collection<T> entityList);
    // 插入(批量)
    boolean saveBatch(Collection<T> entityList, int batchSize); // batchSize:插入批次数量
  • SaveOrUpdate

    1
    2
    3
    4
    5
    6
    7
    8
    // TableId 注解存在更新记录,否插入一条记录
    boolean saveOrUpdate(T entity);
    // 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
    boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList);
    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
  • Remove

    1
    2
    3
    4
    5
    6
    7
    8
    // 根据 queryWrapper 设置的条件,删除记录
    boolean remove(Wrapper<T> queryWrapper);
    // 根据 ID 删除
    boolean removeById(Serializable id); // 主键ID
    // 根据 columnMap 条件,删除记录
    boolean removeByMap(Map<String, Object> columnMap);
    // 删除(根据ID 批量删除)
    boolean removeByIds(Collection<? extends Serializable> idList); // idList:主键ID列表
  • Update

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
    boolean update(Wrapper<T> updateWrapper);
    // 根据 whereWrapper 条件,更新记录
    boolean update(T updateEntity, Wrapper<T> whereWrapper);
    // 根据 ID 选择修改
    boolean updateById(T entity);
    // 根据ID 批量更新
    boolean updateBatchById(Collection<T> entityList);
    // 根据ID 批量更新
    boolean updateBatchById(Collection<T> entityList, int batchSize);
  • Get

    1
    2
    3
    4
    5
    6
    7
    8
    // 根据 ID 查询
    T getById(Serializable id);
    // 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
    T getOne(Wrapper<T> queryWrapper);
    // 根据 Wrapper,查询一条记录
    T getOne(Wrapper<T> queryWrapper, boolean throwEx);
    // 根据 Wrapper,查询一条记录
    Map<String, Object> getMap(Wrapper<T> queryWrapper);
  • List

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 查询所有
    List<T> list();
    // 查询列表
    List<T> list(Wrapper<T> queryWrapper);
    // 查询(根据ID 批量查询)
    Collection<T> listByIds(Collection<? extends Serializable> idList);
    // 查询(根据 columnMap 条件)
    Collection<T> listByMap(Map<String, Object> columnMap);
    // 查询所有列表
    List<Map<String, Object>> listMaps();
    // 查询列表
    List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
    // 查询全部记录
    List<Object> listObjs();
    // 根据 Wrapper 条件,查询全部记录
    List<Object> listObjs(Wrapper<T> queryWrapper);
  • Page

    1
    2
    3
    4
    5
    6
    7
    8
    // 无条件分页查询
    IPage<T> page(IPage<T> page);
    // 条件分页查询
    IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
    // 无条件分页查询
    IPage<Map<String, Object>> pageMaps(IPage<T> page);
    // 条件分页查询
    IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
  • Count

    1
    2
    3
    4
    // 查询总记录数
    int count();
    // 根据 Wrapper 条件,查询总记录数
    int count(Wrapper<T> queryWrapper);

Mapper CRUD 接口

通用 CRUD 封装 BaseMapper 接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器。

  • Insert

    1
    2
    // 插入一条记录
    int insert(T entity);
  • Delete

    1
    2
    3
    4
    5
    6
    7
    8
    // 根据 entity 条件,删除记录
    int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    // 删除(根据ID 批量删除)
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    // 根据 ID 删除
    int deleteById(Serializable id);
    // 根据 columnMap 条件,删除记录
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
  • Update

    1
    2
    3
    4
    // 根据 whereWrapper 条件,更新记录
    int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
    // 根据 ID 修改
    int updateById(@Param(Constants.ENTITY) T entity);
  • Select

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 根据 ID 查询
    T selectById(Serializable id);
    // 根据 entity 条件,查询一条记录
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    // 查询(根据ID 批量查询)
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    // 根据 entity 条件,查询全部记录
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 查询(根据 columnMap 条件)
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    // 根据 Wrapper 条件,查询全部记录
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    // 根据 entity 条件,查询全部记录(并翻页)
    IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询全部记录(并翻页)
    IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据 Wrapper 条件,查询总记录数
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

条件构造器

AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件。

以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getIdEntity为实体类,getId为字段idgetter Method)。

  • allEq:全部eq(或个别isNull)

    1
    2
    3
    allEq(Map<R, V> params)
    allEq(Map<R, V> params, boolean null2IsNull)
    allEq(boolean condition, Map<R, V> params, boolean null2IsNull)

    params : key为数据库字段名,value为字段值
    null2IsNull : 为true则在mapvaluenull时调用isNull方法,为false时则忽略valuenull的值

    • 例1: allEq({id:1,name:"老王",age:null})—>id = 1 and name = '老王' and age is null
    • 例2: allEq({id:1,name:"老王",age:null}, false)—>id = 1 and name = '老王'
  • eq:等于 =

    1
    2
    eq(R column, Object val)
    eq(boolean condition, R column, Object val)
  • ne:不等于 <> (或 !=)

  • gt:大于 >

  • ge:大于等于 >=

  • lt:小于 <

  • le:小于等于 <=

  • between:BETWEEN 值1 AND 值2

    1
    2
    3
    between(R column, Object val1, Object val2)
    between(boolean condition, R column, Object val1, Object val2)
    // between("age", 18, 30)--->age between 18 and 30
  • notBetween:NOT BETWEEN 值1 AND 值2

  • like

  • notLike

  • likeLeft

  • likeRight

  • isNull

    1
    2
    isNull(R column)
    isNull(boolean condition, R column)
  • isNotNull

  • in

    1
    2
    in(R column, Collection<?> value)
    in(boolean condition, R column, Collection<?> value)
  • groupBy

    1
    2
    3
    groupBy(R... columns)
    groupBy(boolean condition, R... columns)
    // groupBy("id", "name")--->group by id,name
  • orderByAsc:升序排序

    1
    2
    orderByAsc(R... columns)
    orderByAsc(boolean condition, R... columns)
  • orderByDesc:升序排序

  • or:主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)

    1
    2
    3
    or(Consumer<Param> consumer)
    or(boolean condition, Consumer<Param> consumer)
    // eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'

不是全部,条件构造器API:https://baomidou.com/pages/10c804/#querywrapper。

QueryWrapper或者LambdaQueryWrapper,继承自 AbstractWrapper 。

  • select:设置查询字段

    1
    2
    3
    4
    select(String... sqlSelect)
    select(Predicate<TableFieldInfo> predicate)
    select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
    // select("id", "name", "age")

UpdateWrapper或者LambdaUpdateWrapper,也继承自 AbstractWrapper。

  • set

    1
    2
    3
    set(String column, Object val)
    set(boolean condition, String column, Object val)
    // set("name", "老李头")
  • setSql:设置 SET 部分 SQL

    1
    2
    setSql(String sql) 
    // setSql("name = '老李头'")
  • lambda:获取 LambdaWrapper,在QueryWrapper中是获取LambdaQueryWrapperUpdateWrapper中是获取LambdaUpdateWrapper

代码生成器

安装

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>

使用

https://baomidou.com/pages/779a6e/#%E4%BD%BF%E7%94%A8