Mybatis-plus


Mybatis-Plus

简介

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

image-20220326181619453

image-20220326181644295

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作,BaseMapper
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求,以后简单的CRUD操作,不用自己编写了 !
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动帮你生成代码)
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

官方链接:快速开始 | MyBatis-Plus (baomidou.com)

使用第三方组件:

  1. 导入对应的依赖
  2. 研究依赖如何配置
  3. 代码如何编写
  4. 提高扩展技术能力

步骤

  1. 创建数据库mybatis_plus

  2. 创建user表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    DROP TABLE IF EXISTS USER;

    CREATE TABLE USER
    (
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
    );

    DELETE FROM USER;

    INSERT INTO USER (id, NAME, age, email) VALUES
    (1, 'Jone', 18, 'test1@baomidou.com'),
    (2, 'Jack', 20, 'test2@baomidou.com'),
    (3, 'Tom', 28, 'test3@baomidou.com'),
    (4, 'Sandy', 21, 'test4@baomidou.com'),
    (5, 'Billie', 24, 'test5@baomidou.com');
  3. 编写项目,初始化项目!使用SpringBoot初始化

  4. 导入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!--数据库驱动-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--lombok-->
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    </dependency>
    <!--mybatis-plus-->
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.0</version>
    </dependency>

    说明:我们使用mybatis-puls可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus !版本的差异

  5. 连接数据库,这一步和mybatis相同

    1
    2
    3
    4
    5
    6
    7
    8
    # 数据库连接配置
    spring.datasource.username=root
    spring.datasource.password=cjy521213
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    #mysql5~8 驱动不同driver-class-name 8需要增加时区的配置serverTimezone=UTC
    #useSSL=false 安全连接

6. 传统方式:pojo-dao(连接mybatis,配置mapper.xml文件)-service-controller==

  1. 使用mybatis-plus之后:

    • pojo

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {

      private long id;
      private String name;
      private Integer age;
      private String email;
      }
    • mapper接口

      1
      2
      3
      4
      5
      6
      //在对应的接口上面继承一个基本的接口 BaseMapper
      @Repository //代表持久层
      public interface UserMapper extends BaseMapper<User> {
      //所有CRUD操作都编写完成了,
      // 不用像以前一样配置一大堆文件
      }
    • 在主启动类添加@MapperScan注解

      1
      2
      3
      4
      5
      6
      7
      8
      9
      //扫描mapper包下的所有接口
      @MapperScan("com.xcw.mapper")
      @SpringBootApplication
      public class MybatisPlusApplication {

      public static void main(String[] args) {
      SpringApplication.run(MybatisPlusApplication.class, args);
      }
      }
  2. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @SpringBootTest
    class MybatisPlusApplicationTests {

    //继承了BaseMapper,所有的方法都来自父类,我们也可以编写自己的扩展方法!
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {

    //参数是一个wrapper ,条件构造器,这里我们先不用 null
    List<User> users = userMapper.selectList(null);//查询全部的用户
    for (User user : users) {
    System.out.println(user);
    }
    }
    }

    image-20220326184552882

思考问题

  • SQL谁帮我们写的? Mybatis-plus都写好了
  • 方法那里来的?Mybatis-plus都写好了

配置日志

我们所有的sql是不可见的,我们希望知道他们是怎么执行的,所以要配置日志知道

1
2
# 配置日志 log-impl:日志实现
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

image-20220326200336877

CRUD扩展

Insert

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void insertTest(){
User user = new User();
user.setName("行初雾");
user.setAge(23);
user.setEmail("1092315259@qq.com");

int insert = userMapper.insert(user); //会帮我们自动生成id
System.out.println(insert);
System.out.println(user);

}

image-20220326201747679

数据库插入的id的默认值为:全局的唯一id

主键生成策略

源码解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public enum IdType {
/**
* 数据库ID自增
* <p>该类型请确保数据库设置了 ID自增 否则无效</p>
*/
AUTO(0),
/**
* 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),

/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 分配ID (主键类型为number或string),
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
*
* @since 3.3.0
*/
ASSIGN_ID(3),
/**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4);
}

默认:ASSIGN_ID 全局唯一Id

分布式系统唯一id生成:

分布式系统唯一Id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

  • Twitter的snowflake算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心(北京、香港···),5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。

主键自增:AUTO 我们需要配置主键自增

我们需要配置主键自增

  • 在实体类字段上配置@TableId(type = IdType.AUTO)
  • 数据库字段一定得是自增

image-20220326203255319

image-20220326203310759

手动输入:INPUT 就需要自己写id

  • 在实体类字段上配置@TableId(type = IdType.INPUT)

image-20220326203507363

Update

1
2
3
4
5
6
7
8
9
10
11
12
@Test    //测试更新
public void updateTest(){
User user = new User();
user.setId(2L);
//通过条件自动拼接动态sql
user.setName("行初雾");
user.setAge(22);
user.setEmail("1092315259@qq.com");

int i = userMapper.updateById(user);//updateById,但是参数是个user
System.out.println(i);
}

image-20220326205008150

image-20220326205027548

自动填充

创建时间、更改时间! 这些操作一般都是自动化完成,我们不希望手动更新

阿里巴巴开发手册︰几乎所有的表都要配置 gmt_create、gmt_modified !而且需要自动化

方式一:数据库级别(工作中不允许修改数据库级别)

  1. 在表中增加字段:create_time,update_time

    image-20220326210023601

  2. 再次测试插入或更新方法,我们需要在实体类中同步

    1
    2
    private Date createTime;
    private Date updateTime;
  3. 查看结果

image-20220326210148070

方式二:代码级别

  1. 删除数据库的默认值,更新操作

    image-20220326210318022

  2. 实体类字段属性上需要增加注解

    1
    2
    3
    4
    @TableField(fill = FieldFill.INSERT)    //value = ("create_time")
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
  3. 编写处理器来处理这个注解即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Slf4j
    @Component //丢到springboot里, 一定不要忘记把处理器加到IOC容器中
    public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override //插入时的填充策略
    public void insertFill(MetaObject metaObject) {
    log.info("==start insert ...... ==");
    //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
    this.setFieldValByName("createTime",new Date(),metaObject);
    this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override //更新时的填充策略
    public void updateFill(MetaObject metaObject) {
    log.info("==start update ...... ==");
    this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    }

  4. 测试插入/更新,观察时间

image-20220326211855378

乐观锁&悲观锁

在面试过程中经常被问到乐观锁/悲观锁,这个其实很简单

乐观锁:顾名思义十分乐观,它总是认为不会出现问题,无论干什么都不上锁!如果出现了问题,再次更新值测试

悲观锁:顾名思义十分悲观,他总是认为出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解 乐观锁机制!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
1
2
3
4
5
6
7
乐观锁:先查询,获得版本号
-- A
update user set name = "wsk",version = version+1
where id = 1 and version = 1
-- B (B线程抢先完成,此时version=2,会导致A线程修改失败!)
update user set name = "wsk",version = version+1
where id = 1 and version = 1

测试一下Mybatis-Plus乐观锁插件

1、给数据库中增加version字段

image-20220326222139727

image-20220326222151868

2、实体类加对应的字段

1
2
@Version    //乐观锁version注解
private Integer version;

3、注册组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//主启动类@MapperScan注解移到配置类中
//扫描mapper包下的所有接口
@MapperScan("com.xcw.mapper")
@EnableTransactionManagement //自动管理事务
@Configuration //配置类
public class MybatisPlusConfig {

//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}

4、测试一下

  • 成功

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //测试乐观锁成功
    @Test
    public void OptimisticLockerTest(){
    //1. 查询用户信息
    User user = userMapper.selectById(1L);
    //2. 修改用户信息
    user.setAge(18);
    user.setEmail("1092315259@qq.com");
    //3. 执行更新操作
    userMapper.updateById(user);
    }

    image-20220326224413554

    image-20220326224436766

  • 失败

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //测试乐观锁失败
    @Test
    public void OptimisticLockerTest2(){
    //线程1
    User user = userMapper.selectById(1L);
    user.setAge(18);
    user.setEmail("1092315259@qq.com");

    //模拟另外一个线程执行力插队操作
    User user2 = userMapper.selectById(1L);
    user2.setAge(19);
    user2.setEmail("1092315259@qq.com");
    userMapper.updateById(user2);

    //自旋锁来多次尝试提交!
    userMapper.updateById(user); //如果没有乐观锁就会覆盖插队线程的值
    }

    image-20220326224857221

    image-20220326224934914

Select

  • 通过id查询单个用户

    1
    2
    3
    4
    5
    6
    //通过id查询单个用户
    @Test
    public void SelectByIdTest(){
    User user = userMapper.selectById(1L);
    System.out.println(user);
    }

    image-20220326230419650

  • 通过id查询多个用户

    1
    2
    3
    4
    5
    6
    7
    8
    //通过id查询多个用户
    @Test
    public void SelectBatchIdsTest(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    for (User user : users) {
    System.out.println(user);
    }
    }

    image-20220326230459869

  • 条件查询 通过map封装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //通过条件查询之一  map
    @Test
    public void MapTest(){
    HashMap<String, Object> map = new HashMap<>();
    //自定义要查询的
    map.put("name","行初雾");
    map.put("age",23);

    List<User> users = userMapper.selectByMap(map);
    for (User user : users) {
    System.out.println(user);
    }
    }

    image-20220326230814437

分页查询

分页在网站的使用十分之多!

1、原始的limit分页

2、pageHelper第三方插件

3、MybatisPlus其实也内置了分页插件!

如何使用:

  1. 配置拦截器组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //mp插件主体
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    //乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    //分页插件
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
    return interceptor;
    }
  2. 直接使用page对象即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //测试分页查询
    @Test
    public void pageTest(){
    //参数一current:当前页 参数二size:页面大小
    //使用了分页插件之后,所以的分页操作都变得简单了
    Page<User> page = new Page<User>(2,5);
    userMapper.selectPage(page,null);

    List<User> users = page.getRecords();
    for (User user : users) {
    System.out.println(user);
    }
    System.out.println("总页数==>"+page.getTotal());
    }

image-20220326232446234

Delete

基本的删除任务:

image-20220326233347524

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//测试删除
@Test
public void deleteByIdTest(){
userMapper.deleteById(1507693097548079105L);
}
@Test
public void deleteBatchIdsTest(){
userMapper.deleteBatchIds(Arrays.asList(1507693097548079106L,1507693097548079107L));
}
@Test
public void deleteByMapTest(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","行初雾");
userMapper.deleteByMap(map);
}

我们在工作中会遇到一些问题:逻辑删除!

逻辑删除

物理删除:从数据库中直接删除

逻辑删除:在数据库中没有被删除,而是通过一个变量来使他失效! deleted=0 ==> deleted=1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

*测试一下:*

  1. 在数据表中增加一个deleted字段

    image-20220326233922894

  2. 实体类中添加对应属性

    1
    2
    @TableLogic   //逻辑删除注解
    private Integer deleted;
  3. 配置!

    1
    2
    3
    #配置逻辑删除  没删除的为0 删除的为1
    mybatis-plus.global-config.db-config.logic-delete-value=1
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
  4. 测试一下删除

    image-20220326234430758

    image-20220326234410683

发现: 记录还在,deleted变为1

再次测试查询被删除的用户,发现查询为空

image-20220326234507234

image-20220326234530217

以上所有的CRUD及其扩展操作,我们都必须精通掌握!会大大提高工作写项目的效率!

条件构造器

十分重要:Wrapper 记住查看输出的SQL进行分析

  1. 测试一

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Test
    void contextLoads() {
    //参数是一个wrapper,条件构造器,和刚才的map对比学习
    //查询name不为空,email不为空,age大于18的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
    .isNotNull("name")
    .isNotNull("email")
    .ge("age",18);
    List<User> users = userMapper.selectList(wrapper);
    for (User user : users) {
    System.out.println(user);
    }
    }
  2. 测试二

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Test
    void warpperTest2() {
    //查询name=Tom的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
    .eq("name","Tom");
    //查询一个数据selectOne,若查询出多个会报错
    //Expected one result (or null) to be returned by selectOne(), but found: *
    //若出现多个结果使用list或map
    User user = userMapper.selectOne(wrapper);
    System.out.println(user);
    }
  3. 测试三

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Test
    void warpperTest3() {
    //查询age在20~30之间的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.between("age",20,30);

    Long count = userMapper.selectCount(wrapper);//输出查询的数量selectCount
    System.out.println(count);
    }
  4. 测试四

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Test
    void warpperTest4() {
    //模糊查询
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
    .notLike("name","m")
    .likeRight("email","t"); //t% 右

    List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
    for (Map<String, Object> map : maps) {
    System.out.println(map);
    }
    }
  5. 测试五

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Test
    void warpperTest5() {
    //模糊查询
    //SELECT id,name,age,email,version,deleted,create_time,update_time
    // FROM user WHERE deleted=0 AND
    // (id IN (select id from user where id<3))
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //id 在子查询中查出来
    wrapper.inSql("id","select id from user where id<3");

    List<Object> objects = userMapper.selectObjs(wrapper);
    objects.forEach(System.out::println);
    }
  6. 测试六

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Test
    void warpperTest6() {

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //通过id进行降序排序
    wrapper.orderByDesc("id");

    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
    }

Mysql => JDBC => Mybatis => MybatisPlus

代码自动生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.wsk;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
//代码自动生成器
public class WskCode {
public static void main(String[] args) {
//我们需要构建一个代码生成器对象
AutoGenerator mpg = new AutoGenerator();
//怎么样去执行,配置策略
//1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");//获取当前目录
gc.setOutputDir(projectPath+"/src/main/java");//输出到哪个目录
gc.setAuthor("wsk");
gc.setOpen(false);
gc.setFileOverride(false);//是否覆盖
gc.setServiceName("%sService");//去Service的I前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
//2、设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setUrl("jdbc:mysql://localhost:3306/wuye?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("study");
pc.setParent("com.wsk");
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("admin","danyuan","building","room");//设置要映射的表名,只需改这里即可
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);//是否使用lombok开启注解
strategy.setLogicDeleteFieldName("deleted");
//自动填充配置
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtUpdate = new TableFill("gmt_update", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtUpdate);
strategy.setTableFillList(tableFills);
//乐观锁配置
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);//开启驼峰命名
strategy.setControllerMappingHyphenStyle(true);//localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute();//执行
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!--模板引擎 依赖:mybatis-plus代码生成的时候报异常-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!--配置ApiModel在实体类中不生效-->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>spring-boot-starter-swagger</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<!--freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!--beetl-->
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>