MyBatisPlus 常用知识点总结

创建项目

  • 默认 Spring InitializrArtifact必须小写
  • 选中 loombookspring webthymeleafmysql driver。(不需要添加mybatis framework
  • pom.xml文件中导入mybatisplus
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
    

入门Demo

  • 创建User类
package top.twilight0319.mybatisplus.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}
  • 创建UserMapper

BaseMapper : Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
这个 Mapper 支持 id 泛型

package top.twilight0319.mybatisplus.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import top.twilight0319.mybatisplus.entity.User;

public interface UserMapper extends BaseMapper<User> {

}
  • 在启动类上添加@MapperScan(value = "top.twilight0319.mybatisplus")
package top.twilight0319.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan(value = "top.twilight0319.mybatisplus")
@SpringBootApplication
public class MybatisplusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisplusApplication.class, args);
    }

}
  • 编写application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/dbtest?useUnicode=true&charactorEncoding=utf-8
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 编写测试类
package top.twilight0319.mybatisplus.mapper;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;


    @Test
    public void test(){
        userMapper.selectList(null).forEach(System.out::println);
    }
}

常用注解

  • 自动映射字段名和表名
  • 自动映射表字段的下划线和java对象中的驼峰命名

@TableName

映射数据库的表名

@Data
@TableName(value="user")
public class Account {
    private Integer id;
    private String name;
    private Integer age;
}

@TableField(value="column")

  • value 映射非主键字段名

  • exist 表示是否为数据库字段,取值为false则忽略该属性

  • select 是否查询该字段,取值为false则不查询该属性

  • fill 监听修改数据的动作。将对象存入数据库的时候,自动赋值,比如 create_time, update_time

    DEFAULT,    // 不监听动作
    INSERT,     // 插入动作
    UPDATE,     // 更新动作
    INSERT_UPDATE;  // 插入和更新
    
    @Data
    @TableName(value="user")
    public class User {
        @TableId(value="id", type = IdType.NONE)
        private Long id;
        private String name;
        private Integer age;
    
        @TableField(fill = FieldFill.INSERT)
        private Date createTime;
        
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Date updateTime;
    }
    
    /**3.0 版本之前需要在application.yml中配置,新版本用注解注入即可
      global-config:
        meta-object-handler: top.twilight0319.mybatisplus.handler.TimeHandler
    **/
    @Component
    public class TimeHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            setFieldValByName("createTime", new Date(), metaObject);
            setFieldValByName("updateTime", new Date(), metaObject);
        }
        @Override
        public void updateFill(MetaObject metaObject) {
            setFieldValByName("updateTime", new Date(), metaObject);
        }
    }
    
    @Test
    public void update(){
        User user = new User();
        user.setName("张三");
        user.setId(1393736407226277889L);
        userMapper.updateById(user);
    }
    

@TableId

设置主键映射

  • value 映射主键字段的名字,把当前属性匹配到主键字段
  • type 设置主键类型,主键的生成策略, 取值来自枚举类 IdType
@Data
@TableName(value="user")
public class User {
    @TableId(value="id", type = IdType.ASSIGN_UUID)
    private String id;
    private String name;
    private Integer age;
}
public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4),
    
    /** @deprecated */
    @Deprecated
    ID_WORKER(3),
    /** @deprecated */
    @Deprecated
    ID_WORKER_STR(3),
    /** @deprecated */
    @Deprecated
    UUID(4);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}
策略 含义
NONE 默认。如果用户没有指定值,则自动分配(雪花算法)
AUTO 完全采用数据库的策略,忽略用户的输入。数据库自增
INPUT 完全采用开发者的策略,需要开发者手动赋值,如果不赋值则传入NULL
ASSIGN_ID 自动分配(雪花算法)。Long、Integer、String
ASSIGN_UUID MP分配UUID。只能是String
  • 默认情况下(NONE),优先采用用户指定的值。雪花算法的值需要用Long保存。数据库中的字段也需要足够大(bigint)。
    ==>  Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? ) 
    ==> Parameters: 100(Long), 小明(String), 15(Integer)
    <==    Updates: 1
    
  • INPUT情况下,如果不传入主键,则生成的SQLIDNULL。如果数据库设置了自增,那就使用自增策略,没有就报错 (Column 'id' cannot be null)(这是数据库的策略)。
    ==>  Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? ) 
    ==> Parameters: null, 小明(String), 15(Integer)
    <==    Updates: 1
    
  • AUTO 情况下,生成的SQl根本没有ID。所以能不能成功完全取决于数据库。
    ==>  Preparing: INSERT INTO user ( name, age ) VALUES ( ?, ? ) 
    ==> Parameters: 小明(String), 15(Integer)
    
  • ASSIGN_IDASSIGN_UUID 都会优先考虑用户的输入。只要User对象中的字段类型和数据库保持一致就不会报错。
    • ASSIGN_ID 生成的数值会自动转换成String类型的id。所以他也可以保存到字符串字段中。
    • ASSIGN_UUID 生成的值无法转换成数值,所以只能用String

@Version

标记乐观锁。通过version字段保证数据的安全性,当修改数据的时候会以version作为条件,当条件成立才会修改成功。
每次修改数据会自动修改version字段的值,update ... set version = 2 where version = 1

@Configuration
public class MybatisPlusConfiguration {
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }
}

只会修改一条,因为version字段被修改了

User user1 = userMapper.selectById(1393736407226277889L);
user1.setName("李四");
User user2 = userMapper.selectById(1393736407226277889L);
user2.setName("王五");

userMapper.updateById(user1);
userMapper.updateById(user2);
==>  Preparing: UPDATE user SET name=?, age=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
==> Parameters: 李四(String), 15(Integer), 2021-05-16 09:13:49.0(Timestamp), 2021-05-16 10:12:39.051(Timestamp), 2(Integer), 1393736407226277889(Long), 1(Integer)
<==    Updates: 1

==>  Preparing: UPDATE user SET name=?, age=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
==> Parameters: 王五(String), 15(Integer), 2021-05-16 09:13:49.0(Timestamp), 2021-05-16 10:12:39.058(Timestamp), 2(Integer), 1393736407226277889(Long), 1(Integer)
<==    Updates: 0

@EnumValue

枚举类注解,将数据库字段映射成实体类的枚举类型成员。

// 枚举类型
public enum MyEnum {
    WORK(0, "上班"),
    REST(1, "休息");

    @EnumValue
    private Integer code;
    private String msg;

    MyEnum(Integer code, String msg){
        this.code = code;
        this.msg = msg;
    }
}

配置枚举类型所在的package

mybatis-plus:
  type-enums-package: top.twilight0319.mybatisplus.enums
@Data
@TableName(value="user")
public class User {
    @TableId(value="id", type = IdType.NONE)
    private Long id;
    private String name;
    private Integer age;

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

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

    @TableField(value = "version")
    @Version
    private int versionNumber;


    // 自动把数据库中的值转化为枚举类型
    private MyEnum status;
}

使用接口的方式也可

public enum MyEnum2 implements IEnum<Integer> {
    WORK(0, "上班"),
    REST(1, "休息");

    @EnumValue
    private Integer code;
    private String msg;

    MyEnum2(Integer code, String msg){
        this.code = code;
        this.msg = msg;
    }

    @Override
    public Integer getValue() {
        return this.code;
    }
}

@TableLogic

用一个字段表示该记录是否被删除,删除记录时不会真的删除记录,而是修改删除标记位。

  • 数据表添加deleted字段
  • 实体类添加注解
    @TableLogic
    @TableField(value="deleted")
    private int deleted;
    
  • 添加配置
    mybatis-plus:
      global-config:
        db-config:
          logic-not-delete-value: 0
          logic-delete-value: 1
    

删除操作变成了 update 操作,如果没有@TableLogic就会执行 delete 操作

==>  Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0 
==> Parameters: 1(Integer)
<==    Updates: 1

查询语句也会忽略已删除的记录(通过添加where条件):

==>  Preparing: SELECT id,name,age,create_time,update_time,version AS versionNumber,status,deleted FROM user WHERE deleted=0 
==> Parameters: 
<==    Columns: id, name, age, create_time, update_time, versionNumber, status, deleted

增删改查

查询

// 不加任何条件全部查询
userMapper.selectList(null).forEach(System.out::println);

// 用wrapper 包装查询条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "小明");
wrapper.gt("age", 15);
userMapper.selectList(wrapper).forEach(System.out::println);
        
// allEq 多条件, ne 不等于, lt 小于, gt 大于, ge, 
QueryWrapper<User> wrapper = new QueryWrapper<>();
Map<String, Object> map = new HashMap<>();
map.put("name", "小明");
map.put("age", 15);
wrapper.allEq(map);
userMapper.selectList(wrapper).forEach(System.out::println);

// 模糊查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "小");     // %小%
wrapper.likeLeft();             // %小
wrapper.linkRight();            // 小%
userMapper.selectList(wrapper);


// 联合查询 inSQL
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id", "select id from user where id > 200");
wrapper.inSql("id", "select id from user where id <  1393839033125179394");
userMapper.selectList(wrapper).forEach(System.out::println);

==>  Preparing: SELECT id,name,age,create_time,update_time,version AS versionNumber,status,deleted FROM user WHERE deleted=0 AND (id IN (select id from user where id > 200) AND id IN (select id from user where id < 1393839033125179394)) 
==> Parameters: 


// 排序
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
userMapper.selectList(wrapper).forEach(System.out::println);

// 先筛选再排序
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
wrapper.gt("id", 200);
userMapper.selectList(wrapper).forEach(System.out::println);

==>  Preparing: SELECT id,name,age,create_time,update_time,version AS versionNumber,status,deleted FROM user WHERE deleted=0 AND (id > ?) ORDER BY id DESC 
==> Parameters: 200(Integer)
// 根据指定id查询
User user = userMapper.selectById(100);
System.out.println(user);

// 查询批量的id,不存在的id会跳过
userMapper.selectBatchIds(Arrays.asList(100, 101, 102));

// 只能做等值判断,逻辑判断需要wrapper
Map<String, Object> map = new HashMap<>();
map.put("name", "小明");
map.put("age", 15);
userMapper.selectByMap(map);

// 查询数量
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 15);
userMapper.selectCount(wrapper);        // 筛选后的计数
userMapper.selectCount(null);           // 所有数量

// 将查询的结果封装到Map中
mapper.selectMaps(wrapper).forEach(...);
mapper.selectList(wrapper).forEach(...);

分页查询

// 帮助自动完成分页
@Bean
public PaginationInterceptor paginationInterceptor(){
    return new PaginationInterceptor();
}

// 返回第一页的数据,每页数据两条
Page<User> page = new Page<>(1, 2);
Page<User> userPage = userMapper.selectPage(page, null);
System.out.println(userPage.getCurrent());      // 返回当前页位置,从0开始
System.out.println(userPage.getSize());         // 返回分页的大小
System.out.println(userPage.getTotal());        // 返回表记录的总数
userPage.getRecords().forEach(System.out::println); // 返回当前页的记录

// 将返回结果封装成Map
Page<Map<String, Object>> page = new Page<>(1, 2);
List<Map<String, Object>> records = userMapper.selectMapsPage(page, null).getRecords();
records.forEach(System.out::println);

==>  Preparing: SELECT id,name,age,create_time,update_time,version AS versionNumber,status,deleted FROM user WHERE deleted=0 LIMIT ?,? 
==> Parameters: 0(Long), 2(Long)
<==    Columns: id, name, age, create_time, update_time, versionNumber, status, deleted
<==        Row: 1, tom, 10, null, null, 0, 0, 0
<==        Row: 100, 小明, 15, null, null, 0, 0, 0
<==      Total: 2
// 返回所有主键
userMapper.selectObjs(null).forEach(System.out::println);
// 查询一个,结果只能是一条记录,否则会报错。
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id", 100);
userMapper.selectOne(wrapper);

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 10

添加

只有这一个方法

User user = new User();
user.setId(11111L);
user.setName("小红");
user.setAge(25);
userMapper.insert(user);
System.out.println(user);

删除

@Test
public void delete(){
    // 根据id删除
    int i1 = userMapper.deleteById(1);

    // 根据id列表删除
    int i2 = userMapper.deleteBatchIds(Arrays.asList(1393605031051239426L, 11111L));

    // 根据wrapper的条件删除
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("age", 15);
    int i3 = userMapper.delete(wrapper);

    // 根据map指定的等式删除
    Map<String, Object> map = new HashMap<>();
    map.put("name", "李四");
    int i4 = userMapper.deleteByMap(map);
}

修改

  • 只有在传入user对象的时候,才会调用 fillHandler 和乐观锁 @Version。(即使user所有属性都为null也是一样)
  • 空的user对象,version默认是0, 所以会被update1

1. 根据id修改

User user = new User(); 
user.setId(1L);
mapper.updateById(user);

2. 根据 wrapper 修改

  1. 根据wrapper中的条件, 把指定行的值修改为user中的属性值。

    User user = userMapper.selectById(1);
    user.setName("小红");
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("age", 25);
    userMapper.update(user, wrapper);
    
    ==>  Preparing: UPDATE user SET name=?, age=?, update_time=?, version=?, status=? WHERE deleted=0 AND (age = ? AND version = ?) 
    ==> Parameters: 小红(String), 10(Integer), 2021-05-25 01:03:38.129(Timestamp), 1(Integer), 0(Integer), 25(Integer), 0(Integer)
    <==    Updates: 1
    

    对于只有一个属性的实体,会忽略其他的属性值。(update_time和乐观锁version除外)

    User user = new User();
    user.setName("小红");
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("age", 25);
    userMapper.update(user, wrapper);
    
    ==>  Preparing: UPDATE user SET name=?, update_time=?, version=? WHERE deleted=0 AND (age = ? AND version = ?) 
    ==> Parameters: 小红(String), 2021-05-25 01:07:16.463(Timestamp), 1(Integer), 25(Integer), 0(Integer)
    <==    Updates: 0
    
  2. 使用 UpdateWrapper 替换实体类的赋值。(会忽略update_time和乐观锁version

    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.set("age", 30).eq("name", "小红");
    userMapper.update(null, wrapper);
    
    ==>  Preparing: UPDATE user SET age=? WHERE deleted=0 AND (name = ?) 
    ==> Parameters: 30(Integer), 小红(String)
    <==    Updates: 1
    

    User类和Wrapper中出现了重复的条件时,各个条件都会被依次追加到set语句中。顺序是先追加User的非空属性,再追加wrapper中定义的属性,所以wrapper中的属性会覆盖User. User 中的属性会被wrapper覆盖。

    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.set("age", 30).eq("name", "小红");
    User user = new User();
    user.setAge(50);
    userMapper.update(user, wrapper);
    
    // 有两个age
    ==>  Preparing: UPDATE user SET age=?, update_time=?, version=?, age=? WHERE deleted=0 AND (name = ? AND version = ?) 
    ==> Parameters: 50(Integer), 2021-05-25 01:19:17.147(Timestamp), 1(Integer), 30(Integer), 小红(String), 0(Integer)
    <==    Updates: 0
    

3. 使用 lambda构造器

LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getName, "小红").set(User::getAge, 30);
User user = new User();
user.setAge(50);
Integer rows = userMapper.update(user, lambdaUpdateWrapper);

和之前一样会覆盖User中的属性

==>  Preparing: UPDATE user SET age=?, update_time=?, version=?, age=? WHERE deleted=0 AND (name = ? AND version = ?) 
==> Parameters: 50(Integer), 2021-05-25 01:29:57.392(Timestamp), 1(Integer), 30(Integer), 小红(String), 0(Integer)
<==    Updates: 0

自定义SQL

注解

  • 编写 DeviceVO. 属性名和字段名要保持一致,这样才能对应上。
    @Data
    public class DeviceVO {
        private int id;
        private String name;
        private BigInteger userId;
        private String userName;
    }
    
  • 编写mapper方法
    @Select(value="select device.*, user.name user_name from device, user where device.user_id=user.id and user.id=#{id};")
    List<DeviceVO> deviceList(Integer id);
    
  • 测试
    userMapper.deviceList(100).forEach(System.out::println);
    

在 mapper.xml文件中定义自定义语句

  • IDEA中不会将src下的配置文件复制到target目录下。所以最好放在resources目录下。默认目录是 resources/mapper/*.xml,可以手动配置所需要的xml文件
    mybatis-plus:
      # 默认是/mapper/*.xml
      mapper-locations: /mapper/*.xml
    
  • #{user.name}${eq.customSqlSegment} 不同。#是占位符?,之后的可以将变量的值替换?,而$是字符串拼接。比如select * from user WHERE (id = ?) 中的WHERE (id = ?)就是select * from user ${eq.customSqlSegment} 的结果
  • #{}可以直接填属性名,而${}需要加上@Param才可以。

select

  • 如果返回多条结果,那么方法的返回值不能写List<User>。但是反过来是可以的,用List<User>也能接受一个对象。
    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 10
    
  • 返回List时,xml中的resultType="top.twilight0319.mybatisplus.entity.DeviceVO"直接写到对应实体类就行。
// 返回多表查询的List
List<DeviceVO> deviceList(Integer id);

// 返回单表的List
List<User> userList();

// 使用wrapper
List<User> userListWrapper(@Param(Constants.WRAPPER) Wrapper<User> wrapper);

// 使用Map保存结果
Map<String, Object> userListMap(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
<select id="deviceList" resultType="top.twilight0319.mybatisplus.entity.DeviceVO">
    select device.*, user.name user_name
    from device, user
    where device.user_id=user.id
    and user.id=#{id};
</select>

<select id="userList" resultType="top.twilight0319.mybatisplus.entity.User">
    select *
    from user
    where deleted=0;
</select>

<select id="userListWrapper" resultType="top.twilight0319.mybatisplus.entity.User">
    select *
    from user
    ${ew.customSqlSegment}
</select>

<select id="userListMap" resultType="java.util.Map">
    select *
    from user
    ${ew.customSqlSegment}
</select>

insert、update、delete

<insert>中不用加返回类型,接口中可以返回 int, long, boolean。如果返回值大于0则boolean为true,否则为false

// 可以在mapper.xml中使用 #{user.attrname}
// 如果不加 @Param 就直接写user的属性名
int insertUser(@Param("user") User user);
<insert id="insertUser" >
    INSERT INTO user
    (id, name, age)
    VALUES(#{user.id}, #{user.name}, #{user.age});
</insert>

代码生成器

根据数据表自动生成实体类,Mapper, Service,ServiceImpl, Controller

  1. pom.xml 导入 Mybatisplus generator
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>

使用时直接修改参数即可

package top.twilight0319.mybatisplus;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
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.NamingStrategy;

public class Main {
    public static void main(String[] args) {
        //创建generator对象
        AutoGenerator autoGenerator = new AutoGenerator();
        //数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/dbtest?useUnicode=true&characterEncoding=UTF-8");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("123456");
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        autoGenerator.setDataSource(dataSourceConfig);

        //全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
        globalConfig.setOpen(false);                // true时会打开一个windows资源管理器
        globalConfig.setAuthor("twilight");
        globalConfig.setServiceName("%sService");   // 避免接口前出现I
        autoGenerator.setGlobalConfig(globalConfig);

        //包信息
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("top.twilight0319.mybatisplus.generate");
        packageConfig.setController("controller");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setMapper("mapper");
        packageConfig.setEntity("entity");
        autoGenerator.setPackageInfo(packageConfig);

        //配置策略
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setInclude("user", "device");           // 只映射部分表
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        autoGenerator.setStrategy(strategyConfig);

        autoGenerator.execute();
    }
}

注意下面两个包的版本要一致:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.1</version>
</dependency>

原文地址:https://www.cnblogs.com/twilight0402/p/14807963.html