MyBatis‑Plus 学习笔记

MyBatis‑Plus 学习笔记

MyBatis‑Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatis‑Plus 特性

  1. 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
  2. 损耗小:启动即会自动注入基本 CRUD,性能基本无损耗,直接面向对象操作。
  3. 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作;更有强大的条件构造器,满足各类使用需求。
  4. 支持 Lambda 形式调用:通过 Lambda 表达式,方便编写各类查询条件,无需担心字段写错。
  5. 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器‑Sequence),可自由配置,完美解决主键问题。
  6. 支持 ActiveRecord 模式:实体类继承 Model 类,就可以直接完成 CRUD 调用。
  7. 支持自定义全局通用操作:支持全局通用方法注入(Write once, use anywhere)。
  8. 内置代码生成器:代码 / Maven 插件快速生成 Mapper、Model、Service、Controller 层代码,支持模板引擎,大量自定义配置。
  9. 内置分页插件:基于 MyBatis 物理分页,配置插件后,分页写法和普通 List 查询几乎一样。
  10. 多数据库支持:分页插件支持 MySQL、MariaDB、Oracle、DB2、H2、Postgre、SQLServer 等数据库。
  11. 内置性能分析插件:输出SQL语句和执行耗时,开发测试使用,快速定位慢查询。
  12. 内置全局拦截插件:智能阻断全表 delete、update,防止误操作;支持自定义拦截规则。

CRUD 概念

CRUD:数据库的4个基本操作

  • C Create:增加(插入)
  • R Read:读取(查询)
  • U Update:更新(修改)
  • D Delete:删除

数据库四大语言

1. DDL 数据定义语言(Data Definition Language)

用于定义数据库对象:数据库、表、视图、索引等。

示例:create table、alter table、drop table

2. DML 数据操纵语言(Data Manipulation Language)

用于操作表里面的数据记录,做新增、修改、删除(不包含查询)。

示例:insert、update、delete

3. DCL 数据控制语言(Data Control Language)

用于权限管理、事务控制。

示例:grant、revoke、事务相关语句

4. DQL 数据查询语言(Data Query Language)

专门做数据表记录的查询操作。

示例:select


MP核心代码速览(来自测试代码)

1)BaseMapper 基础CRUD

⚠️注意:updateById:判断实体属性是否为null来决定是否加入SET;
如果属性是基本类型int age,默认值0不为null,会把0更新到数据库,实体尽量使用包装类Integer age。

功能分类 Mapper(BaseMapper)示例代码 Service(IService)示例代码 说明
新增单条 int row = userMapper.insert(user); boolean ok = userService.save(user); Mapper 返回影响行数;Service 返回 true/false
批量新增 ❌无原生批量新增需自己手写 boolean ok = userService.saveBatch(list); MP 默认循环单条 insert;url 添加rewriteBatchedStatements=true开启数据库真实批量
根据 id 删除 int row = userMapper.deleteById(1L); boolean ok = userService.removeById(1L);
批量 id 删除 int row = userMapper.deleteBatchIds(ids); boolean ok = userService.removeByIds(ids); ids 为集合List<Long>
按条件删除 int row = userMapper.delete(wrapper); boolean ok = userService.remove(wrapper); 传入 QueryWrapper 条件
根据 id 修改 int row = userMapper.updateById(user); boolean ok = userService.updateById(user); 只更新实体中非 null 属性
条件修改 int row = userMapper.update(user,updateWrapper); boolean ok = userService.update(user,updateWrapper); 按 Wrapper 条件更新记录
保存或更新 ❌无该方法 boolean ok = userService.saveOrUpdate(user); id 不为 null 执行 updateById;id 为 null 执行 insert
根据 id 查询 User user = userMapper.selectById(1L); User user = userService.getById(1L); 查不到返回null
批量 id 查询 List<User> list = userMapper.selectBatchIds(ids); List<User> list = userService.listByIds(ids);
查询单条 User user = userMapper.selectOne(wrapper); User user = userService.getOne(wrapper); 查询到多条时抛出异常
查询总条数 Long count = userMapper.selectCount(wrapper); Long count = userService.count(wrapper);
查询列表 List<User> list = userMapper.selectList(wrapper); List<User> list = userService.list(wrapper);
分页查询 IPage<User> page = userMapper.selectPage(pageObj,wrapper); IPage<User> page = userService.page(pageObj,wrapper); 需要开启 MP 分页插件,物理分页
Lambda 链式 ❌不支持 java\nList<User> list = userService.lambdaQuery()\n.eq(User::getName,"张三")\n.list();\n Service 独有,使用方法引用,避免硬编码字段名

IPage<User> page = userMapper.selectPage(pageObj,wrapper);相当于limt 加上selectCount(wrapper)

mapper层

public interface UserMapper extends BaseMapper<User> {

    IPage<User> select(IPage<User> page, UserQuery userQuery);
}

service层

实现类

@Service
public class IsUserServiceImpl extends ServiceImpl<UserMapper,User> implements IsUserService {

}

service接口

public interface IsUserService extends IService<User>
{

}

条件构造器 QueryWrapper

方法 含义 SQL等价
eq("name","李四") 等于 name = ?
ne("name","张三") 不等于 name <> ?
gt("age",30) 大于 age > ?
ge("age",31) 大于等于 age >= ?
lt("age",32) 小于 age < ?
le("age",32) 小于等于 age <= ?
between("age",22,28) 区间 age between ? and ?
like("name","张") 模糊查询 name like %张%
likeLeft("name","张") 左通配 name like %张
likeRight("name","李") 右通配 name like 李%
isNull("email") 为空 email is null
in("name","张三","李四") in集合 name in (?,?)
or() 或者 or拼接条件
last("limit 1") 末尾拼接SQL 直接拼接在SQL最后

示例:

QueryWrapper<User> qw = new QueryWrapper<>();
qw.eq("name","张三").or().eq("age",22);
List<User> users = userMapper.selectList(qw);
  /**
     * eq使用
     * eq("列名",值)
     */
    @Test
    public void testEq() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        //组成条件 equals
        qw.eq("name", "李四");
        //WHERE name = ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * ne使用
     * ne表示不等于 <>  not equal
     * <p>
     * ne("列名",值)
     */
    @Test
    public void testNe() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        //组成条件
        qw.ne("name", "张三");
        // WHERE name <> ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * gt 大于( > ) great than
     */
    @Test
    public void testGt() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.gt("age", 30); //age > 30
        // WHERE age > ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * ge 大于等于 ( >=)  great equal
     */
    @Test
    public void testGe() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.ge("age", 31);// >=31
        //WHERE age >= ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * lt 小于 ( < ) less than
     */
    @Test
    public void testLt() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.lt("age", 32);
        // WHERE age < ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * le 小于 ( <= )  less and equal
     */
    @Test
    public void testLe() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.le("age", 32);
        //  WHERE age <= ?
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * between ( ? and ? )
     */
    @Test
    public void testBetween() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        //between("列名",开始值,结束值)
        qw.between("age", 22, 28);
        // where age >= 22 and age <= 28
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * notBetween(不在范围区间内)
     */
    @Test
    public void testNotBetween() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.notBetween("age", 18, 28);
        //WHERE age NOT BETWEEN ? AND ?
        // where age < 18 or age > 28
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * like 匹配某个值
     */
    @Test
    public void testLike() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.like("name", "张");
        // WHERE name LIKE %张%
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * notLike 不匹配某个值
     */
    @Test
    public void testNotLike() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.notLike("name", "张");
        //  WHERE name NOT LIKE ?  %张%
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * likeLeft "%值"
     */
    @Test
    public void testLikeLeft() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.likeLeft("name", "张");
        //WHERE name LIKE %张
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * likeRight "%值"
     */
    @Test
    public void testLikeRight() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.likeRight("name", "李");
        //WHERE name LIKE 李%
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    /**
     * isNull , 判断字段是 null
     */
    @Test
    public void testIsNull(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //判断email is null
        //WHERE email IS NULL
        qw.isNull("email");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    /**
     * isNotNull , 判断字段是 is not null
     */
    @Test
    public void testIsNotNull(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        // WHERE email IS NOT NULL
        qw.isNotNull("email");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * in 值列表
     */
    @Test
    public void testIn(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //in(列名,多个值的列表)
        //WHERE name IN (?,?,?)
        qw.in("name","张三","李四","周丽");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }

    }

    /**
     * notIn 不在值列表
     */
    @Test
    public void testNoIn(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //in(列名,多个值的列表)
        //WHERE name NOT IN (?,?,?)
        qw.notIn("name","张三","李四","周丽");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * in 值列表
     */
    @Test
    public void testIn2(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        List<Object> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        //WHERE id IN (?,?)
        qw.in("id",list);
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    /**
     * inSql() : 使用子查询
     */
    @Test
    public void testInSQL(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //select * from user WHERE age IN (select age from User where id=1)
        qw.inSql("age","select age from User where id=1");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    /**
     * notInSql() : 使用子查询
     */
    @Test
    public void testNotInSQL(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //WHERE age NOT IN (select age from User where id=1)
        qw.notInSql("age","select age from User where id=1");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * groupBy:分组
     */
    @Test
    public void testGroupby(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.select("name,count(*) userNumbers");//select name,count(*) userNumbers
        qw.groupBy("name");
        // SELECT name,count(*) userNumbers FROM User GROUP BY name
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

 

    /**
     * orderbyDesc : 按字段降序
     */
    @Test
    public void testOrderByDesc(){
        QueryWrapper<User> qw= new QueryWrapper<>();
        // ORDER BY name DESC , id DESC
        qw.orderByDesc("name","id");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    /**
     * and ,or方法
     */
    @Test
    public void testOr(){
        QueryWrapper<User> qw= new QueryWrapper<>();
        //WHERE name = ? OR age = ?
        qw.eq("name","张三")
                .or()
                .eq("age",22);
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * last : 拼接sql语句到MP的sql语句的最后
     */
    @Test
    public void testLast(){
        QueryWrapper<User> qw = new QueryWrapper<>();
        //SELECT id,name,age,email FROM User WHERE name = ? OR age = ? limit 1
        qw.eq("name","张三")
                .or()
                .eq("age",22)
                .last("limit 1");
        List<User> users = userMapper.selectList(qw);
        for (User user : users) {
            System.out.println(user);
        }
    }


    @Test
    public void testUpdate() {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", 1).set("name", "张三");
        userMapper.update(updateWrapper);
    }
}

分页 IPage

需要先配置MyBatis‑Plus分页插件,才是物理分页。

//Page(当前页,每页条数)
IPage<User> page = new Page<>(1,5);
QueryWrapper<User> qw = new QueryWrapper<>();
qw.gt("age",22);
IPage<User> result = userMapper.selectPage(page, qw);

result.getRecords(); //当前页数据
result.getTotal();   //总条数
result.getPages();   //总页数
result.getCurrent();//当前页码
result.getSize();    //每页大小

自定义XML分页(Mapper接口)

IPage<User> select(IPage<User> page, @Param("userQuery") UserQuery userQuery);

Mapper.xml 中写自己的SQL,第一个参数传IPage,MP自动做分页,不需要手写limit。

逻辑删除

配置MP全局逻辑删除后,调用普通deleteById(),底层执行update set deleted=1,并非真实DELETE; 查询时MP自动拼接 where deleted=0。

@TableLogic(value = "0",delval = "1")
private Integer deleted;

自动填充

创建时间、修改时间,实现MetaObjectHandler,插入/更新自动给字段赋值,不用手动set。

@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

主键生成策略

public enum IdType {    
AUTO(0),  // ID自增    
NONE(1),  // 未设置主键类型    
INPUT(2),  // 用户输入ID   订单编号主键:日期+随机数    
ASSIGN_ID(3), // 雪花算法    
ASSIGN_UUID(4); // UUID }
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;

常见坑总结

  1. updateById:实体尽量使用包装类(Integer而不是int);基本类型默认值0不为null,会误更新。
  2. 代码生成器mybatis‑plus‑generator不会自动引入core,必须引入mybatis‑plus‑boot‑starter,版本保持完全一致。
  3. 分页功能必须配置分页插件,否则是内存分页。
  4. <where>标签只去除条件前面的AND,写在标签外会出现语法错误。
  5. MySQL关键字(delete等)不要用作字段名,否则报语法错误。

反向工程

依赖准备(必须)

<!--MP启动器(核心包,必须,否则报类找不到)-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis‑plus‑boot‑starter</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!--代码生成器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis‑plus‑generator</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!--模板引擎 velocity,生成代码使用-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity‑engine</artifactId>
    <version>2.3</version>
</dependency>
<!--lombok,实体类@Data注解,代码生成器会用到enableLombok()-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

⚠️注意:generator生成器不会自动导入core核心包,必须引入mybatis‑plus‑boot‑starter;三者版本号必须保持一致。

MPGenerator完整代码说明

package com.situ.mp;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.IFill;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Column;

public class MPGenerator {
    //需要配置
    private static final String dbTables = "user";             //需要生成的表名,多张表逗号分隔
    private static final Boolean enableSwagger = false;        //是否开启Swagger注解

    public static void main(String[] args) {
        // ==========1.数据源配置 DataSourceConfig ==========
        // 参数:url,用户名,密码
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/study","root","123456").build();

        // ==========2.全局配置 GlobalConfig ==========
        GlobalConfig.Builder globalConfigBuilder = new GlobalConfig.Builder();
        // 获取项目根路径
        String projectPath = System.getProperty("user.dir");
        System.out.println(projectPath);
        // 设置代码输出目录
        globalConfigBuilder.outputDir(projectPath + "/mpgenerator" + "/src/main/java");
        // 设置代码作者
        globalConfigBuilder.author("dxk");
        // 是否开启Swagger注解
        if (enableSwagger){
            globalConfigBuilder.enableSwagger();
        }
        //日期类型:ONLY_DATE 使用java.util.Date;也可以用TIME_PACK 使用LocalDateTime
        globalConfigBuilder.dateType(DateType.ONLY_DATE);

        // ==========3.包配置 PackageConfig ==========
        PackageConfig.Builder packageConfigBuilder = new PackageConfig.Builder();
        packageConfigBuilder.parent("com.situ.mp");           //父包名
        packageConfigBuilder.entity("pojo");                   //实体类所在包名 com.situ.mp.pojo

        // ==========4.策略配置 StrategyConfig ==========
        StrategyConfig.Builder strategyConfigBuilder = new StrategyConfig.Builder();
        //指定要生成代码的表,多张表用逗号隔开
        strategyConfigBuilder.addInclude(dbTables.split(","));

        //----------实体类策略----------
        strategyConfigBuilder.entityBuilder()
                .idType(IdType.NONE)                        //主键策略,NONE:跟随数据库
                .naming(NamingStrategy.underline_to_camel)  //数据库表名下划线转Java驼峰 user_info → UserInfo
                .columnNaming(NamingStrategy.underline_to_camel) //列名下划线转驼峰 create_time → createTime
                .enableLombok()                              //开启lombok,实体生成@Data注解
                .logicDeleteColumnName("deleted")            //数据库逻辑删除字段名
                .logicDeletePropertyName("deleted");         //实体类逻辑删除属性名

        //自动填充配置:创建时间、更新时间
        IFill gmtCreate = new Column("create_time", FieldFill.INSERT);            //插入时填充
        IFill gmtModified = new Column("update_time", FieldFill.INSERT_UPDATE);   //插入和更新都填充
        strategyConfigBuilder.entityBuilder().addTableFills(gmtCreate, gmtModified);

        //----------Controller策略----------
        strategyConfigBuilder.controllerBuilder()
                .enableRestStyle();          //生成@RestController,否则是@Controller
                //.enableHyphenStyle();      //url地址使用横杠,如 /user‑info

        // ==========组装所有配置,执行生成 ==========
        AutoGenerator autoGenerator = new AutoGenerator(dataSourceConfig);
        autoGenerator.global(globalConfigBuilder.build());
        autoGenerator.packageInfo(packageConfigBuilder.build());
        autoGenerator.strategy(strategyConfigBuilder.build());
        autoGenerator.execute();
    }
}

四大配置模块解析

1. DataSourceConfig 数据源配置

new DataSourceConfig.Builder(jdbcUrl, username, password).build()
  • 作用:连接数据库,读取表结构信息;
  • 需要填写正确的数据库url、账号密码。

2. GlobalConfig 全局配置

配置 作用
outputDir() 代码输出磁盘路径
author("dxk") 设置类上@author作者注释
enableSwagger() 实体类开启Swagger注解,需要Swagger依赖
dateType(DateType.ONLY_DATE) 时间类型;ONLY_DATE=Date,TIME_PACK=LocalDateTime

System.getProperty("user.dir") 获取当前项目根目录。

3. PackageConfig 包配置

  • parent("com.situ.mp"):根包;
  • entity("pojo"):实体类输出包,最终全包名 com.situ.mp.pojo;

mapper、service、controller有默认包名,不写就使用默认。

4. StrategyConfig 策略配置(核心)

  1. addInclude("user"):指定哪些表生成代码;多张表逗号分隔;

addExclude():排除表,不生成。

实体 entityBuilder

配置 说明
idType(IdType.NONE) 主键策略,NONE代表跟随数据库设置AUTO_INCREMENT;也可以ASSIGN_ID雪花算法
naming(underline_to_camel) 表名下划线转驼峰命名
columnNaming(underline_to_camel) 字段下划线转驼峰
enableLombok() 开启Lombok,实体自动加上@Data注解
logicDeleteColumnName / logicDeletePropertyName 逻辑删除数据库字段名、实体属性名
addTableFills() 自动填充字段配置,对应create_time、update_time

Controller controllerBuilder

  • enableRestStyle():生成@RestController;不开启生成普通@Controller
  • enableHyphenStyle():访问路径使用横杠分隔,如 /user‑info

执行生成

AutoGenerator autoGenerator = new AutoGenerator(dataSourceConfig);
autoGenerator.global(globalConfigBuilder.build());
autoGenerator.packageInfo(packageConfigBuilder.build());
autoGenerator.strategy(strategyConfigBuilder.build());
autoGenerator.execute(); //执行代码生成

关键参数说明

  1. IdType.NONE

NONE:不设置主键策略,使用数据库AUTO_INCREMENT自增;
如果写IdType.ASSIGN_ID,使用MP雪花算法生成id,数据库id不要设置AUTO_INCREMENT。

  1. 自动填充 IFill Column
//插入时填充
IFill gmtCreate = new Column("create_time", FieldFill.INSERT);
//插入和更新都填充
IFill gmtModified = new Column("update_time", FieldFill.INSERT_UPDATE);

代码生成器只是给实体加上注解@TableField(fill = FieldFill.INSERT),想要真正自动填充,必须手写实现MetaObjectHandler组件,代码生成器不会生成这个类。

  1. 逻辑删除

代码生成器会给实体属性加上@TableLogic注解,需要在yml配置逻辑删除值,生成器不会写yml配置。

常见坑

  1. 缺少依赖,运行main报NoClassDefFoundError:检查starter、generator、velocity‑engine,版本全部统一。
  2. 输出路径错误:outputDir路径写错,代码找不到生成位置,打印projectPath看项目路径。
  3. idType(IdType.NONE)但是数据库id没有开启AUTO_INCREMENT,插入报读取自增id失败。
  4. 自动填充只生成注解,不会生成MetaObjectHandler处理器,需要自己写。
  5. 逻辑删除只生成@TableLogic注解,yml的逻辑删除配置需要手动写。
  6. 多张表生成:dbTables = "user,student"。

补充:MetaObjectHandler示例(代码生成器不会生成)

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject,"createTime",LocalDateTime::now,LocalDateTime.class);
        this.strictInsertFill(metaObject,"updateTime",LocalDateTime::now,LocalDateTime.class);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject,"updateTime",LocalDateTime::now,LocalDateTime.class);
    }
}

总结:MP代码生成器只生成实体、Mapper、Service、Controller业务代码;配置类(MetaObjectHandler、分页插件)、yml配置文件,需要开发者手动编写。

上一篇
下一篇