一、MP简介

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

1.1、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.2、支持的数据库

任何能使用 mybatis 进行 crud, 并且支持标准 sql 的数据库

二、快速入门

使用一个springboot项目来体验MP的强大之处。

2.1、建立入门项目的数据库与项目

建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create database mp;
use mp;

create table user(
id bigint(20) primary key auto_increment,
name varchar(50),
email varchar(50),
age int
);


insert into
user(name, email, age)
VALUES
('A','a@qq.com',18),
('B','b@qq.com',19),
('C','c@qq.com',12),
('D','d@qq.com',11),
('E','e@qq.com',111);

建立spring-boot项目,引入依赖

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
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>

项目的application.yml配置文件如下

1
2
3
4
5
6
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai
password: tianxin1230.
username: root

编写主启动类

1
2
3
4
5
6
7
@MapperScan("com.hzx.mpblog.mapper")
@SpringBootApplication
public class MpApplication {
public static void main(String[] args) {
SpringApplication.run(MpApplication.class);
}
}

根据数据库表建立对应entity实体类,这里使用Lombok插件并开启链式编程来简化开发

1
2
3
4
5
6
7
8
@Data
@Accessors(chain = true)
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}

编写UserMapper接口,该接口需要继承BaseMapper< T >,其中T为要操作的数据库表对应的实体类

1
2
3
@Repository
public interface UserMapper extends BaseMapper<User> {
}

2.2、编写测试类进行测试

编写测试类,测试mybatis-plus为我们提供的查询所有方法

  • 在selectList中,可以传入一个QueryWrapper查询条件构造器对象,但由于这里需要查询所有对象,所以不加条件筛选,传入null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
@RunWith(SpringRunner.class)
public class MpApplicationTest {
@Autowired
private UserMapper userMapper;


@Test
public void testFindAll() {
List<User> userList = userMapper.selectList(null);
userList.forEach(user ->
System.out.println(user)
);
}
}

结果

image-20210129153047772

2.3、添加配置输出sql语句

我们可以在application.yml中添加配置,让mybatis-plus在执行时输出的sql语句

1
2
3
4
# 打印sql语句
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

重新启动,测试结果

image-20210129153056405

三、CRUD扩展

3.1、insert测试插入数据

使用Mybatis-plus自带的插入方法进行测试

1
2
3
4
5
6
7
8
9
@Test
public void testInsert() {
User user = new User();
user.setName("小明")
.setAge(18)
.setEmail("xiaoming@qq.com");
int result = userMapper.insert(user);
System.out.println(result == 1 ? "插入成功!" : "插入失败!");
}
  • 查看testInsert()的执行结果并再次启动testFindAll()方法

image-20210129153116620

在这次插入操作中,我们没有指定插入数据库对象的id,这个属性是Mybatis-plus为我们生成的,Mybatis-plus提供的主键生成策略在枚举类IdType中.

1
2
3
4
5
6
7
8
public enum IdType {
AUTO(0),
NONE(1),
INPUT(2),
ID_WORKER(3),
UUID(4),
ID_WORKER_STR(5);
}

3.1.1、雪花算法

  • 雪花算法是推特开源的分布式ID生成算法,结果是一个long型的ID。
  • 核心思想是:使用41bit作为毫秒数,10bit作为及其的ID(5个bit是数据中心,5个bit的及其ID),12bit作为毫秒的流水号(意味着每个节点在每秒可以产生4096个Id),最后还有一个符号位永远是0

3.1.2、主键自增

配置主键自增

  • 在实体类字段上使用@TableId(type = IdType.AUTO)
  • 要求数据库字段一定是自增的,否则会报错

3.1.3、其余主键类型

AUTO(0):自增
NONE(1):不使用
INPUT(2):手动输入
ID_WORKER(3):默认唯一全局id
UUID(4):uuid
ID_WORKER_STR(5):默认唯一全局id字符串形式

3.2、update更新操作

使用mybatis-plus提供的updateById方法可以快速修改表中数据,更新Id为2L的对象信息

1
2
3
4
5
6
7
8
9
10
@Test
public void testUpdate() {
User user = new User();
user.setId(2L)
.setName("芜湖")
.setEmail("wuhu@qq.com")
.setAge(18);
int result = userMapper.updateById(user);
System.out.println(result == 1 ? "修改成功!" : "修改失败!");
}
  • 查看结果

image-20210129153136022

3.3、Mybatis-plus的自动填充功能

在实际开发中,数据库往往有create_time和update_time两个字段,对于这两个字段,我们不希望手动填充,而希望程序或者数据库自动填充,mp提供了这个功能。

在数据库中添加create_time和update_time两个属性,并在实体类中添加对于字段。

3.3.1、数据库级别填充

在新建的两个属性下面勾选根据时间戳自动更新即可,这种方式不推荐使用

image-20210129153147791

3.3.2、代码级别自动填充

  • 在实体类的createTime和updateTime字段上添加注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Data
@Accessors(chain = true)
public class User {
private Long id;
private String name;
private Integer age;
private String email;
/***
* 字段添加时填充内容
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/***
* 字段添加/更新时填充内容
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
  • 编写一个处理器用于处理这两个注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);

}

//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
  • 在主启动类中添加组件扫描注解
  • 测试插入,查看是否自动填充
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void testInsert() {
User user = new User();
user.setName("小明111")
.setAge(18)
.setEmail("xiaoming@qq.com");
int result = userMapper.insert(user);
System.out.println(result == 1 ? "插入成功!" : "插入失败!");
}

@Test
public void testUpdate() {
User user = new User();
user.setId(2L)
.setName("芜湖222")
.setEmail("wuhu@qq.com")
.setAge(18);
int result = userMapper.updateById(user);
System.out.println(result == 1 ? "修改成功!" : "修改失败!");
}
  • 启动testFindAll方法查看结果

image-20210129153158628

  • 自动填充使用成功。

3.4、乐观锁和悲观锁

悲观锁十分悲观,他总是认为会出现问题,无论干什么都会上锁!

而乐观锁十分乐观,他总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试。

下面介绍Mybatis-plus中乐观锁的实现方法

3.4.1、乐观锁的实现方式

取出记录时,获取当前version

更新时带上这个version

执行更新时,set version = newVersion where version = oldVersion

如果version不对,就更新失败

  • 例子
1
2
3
4
5
# 乐观锁:
# 1 先查询,获得版本号version = 1
# 假设现有AB两个线程在执行这条update语句,当A未执行完成时,B抢先完成这次更新,那么此时由于版本号version已经为2,所以A线程的更新工作不会成功,此时就保证了线程间的通讯安全

update user set name = "芜湖",version = version + 1 where id = 2 and version = 1;

给数据库表中添加一个version属性

image-20210129153213565

给实体类中添加一个version字段,同时在上面添加一个@Version注解,表明这是一个乐观锁

1
2
@Version
private Integer version;

在配置类中注册乐观锁组件

1
2
3
4
5
6
7
8
9
10
11
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {
/***
* 注册乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}

3.5、select查询操作

3.5.1、根据id查询数据

根据传入的主键值查询数据

1
2
3
4
5
@Test
public void testSelectById() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
  • 结果

image-20210129153228587

3.5.2、根据集合对象查询数据

传入一个主键集合,根据传入的多个主键值查询多条数据,使用selectBatchIds方法,该方法实际上使用mysql中的in关键字

1
2
3
4
5
6
7
@Test
public void testSelectByIds() {
List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 5L));
users.forEach(user ->
System.out.println(user)
);
}
  • 结果

image-20210129153239557

3.5.3、根据Map对象查询数据

传入一个map,mp将会以键为字段,值为字段值进行拼接并查询,如果map中有多个键值对,那么会以and关键词拼接

  • 当map中只有一个键值对时
1
2
3
4
5
6
7
@Test
public void testSelectByMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id",1L);
List<User> users = userMapper.selectByMap(map);
users.forEach(user -> System.out.println(user));
}
  • 结果

image-20210129153248616

  • 当map中包含多个键值对时
1
2
3
4
5
6
7
8
@Test
public void testSelectByMaps() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id",2L);
map.put("name","芜湖222");
List<User> users = userMapper.selectByMap(map);
users.forEach(user -> System.out.println(user));
}
  • 结果

image-20210129153259081

3.5.4、分页查询

一般来说,分页查询的实现有以下几种方式

  • 使用limit关键字进行分页
  • 使用PageHelper和PageInfo等第三方插件进行分页
  • 使用Mybatis-plus自带的分页插件进行分页

下面介绍mp的分页插件

  • 在mybatis-plus配置类中配置拦截器组件
1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testPage() {
/***
* 第一个参数:当前页
* 第二个参数:每页数据条数
*/
Page<User> page = new Page<>(1,2);
//使用Mybatis-plus提供的selectPage方法,传入分页对象page
IPage<User> userIPage = userMapper.selectPage(page, null);
//得到的Page对象中,records属性就是需要的集合,该集合中包含了查询的结果
List<User> records = userIPage.getRecords();
records.forEach(user -> System.out.println(user));
}
  • 结果

image-20210129153308347

3.5.5、分页插件Page属性简介

1
2
3
4
5
6
7
8
9
10
public class Page<T> implements IPage<T> {
private List<T> records;
private long total;
private long size;
private long current;
private String[] ascs;
private String[] descs;
private boolean optimizeCountSql;
private boolean isSearchCount;
}
  • Listrecords–用来存放查询出来的数据
  • long total–返回记录的总数
  • long size–每页显示条数,默认 10
  • long current–当前页,默认1
  • String[] ascs–升序字段集合
  • String[] descs–降序字段集合
  • boolean optimizeCountSql–自动优化count sql,默认为true
  • boolean isSearchCount–是否进行count查询,默认为true

3.6、delete删除操作

3.6.1、根据id删除记录

使用mp提供的deleteById方法,返回值为数据库表中受影响数据条数

1
2
3
4
5
@Test
public void testDeleteById() {
int result = userMapper.deleteById(1L);
System.out.println(result == 1 ? "删除成功!" : "删除失败!");
}
  • 结果

image-20210129153320211

3.6.2、通过传入的集合对象进行批量删除

使用mp提供的deleteBatchIds方法

1
2
3
4
5
@Test
public void testDeleteByIds() {
int result = userMapper.deleteBatchIds(Arrays.asList(2L,3L,1L));
System.out.println(result);
}
  • 结果:由于数据库中id为1L的数据不存在,所以影响的数据条数只有两条,与批量插入一样,使用了mysql中的In关键字

image-20210129153331310

3.6.3、通过传入的map进行删除

与通过map进行查询类似,当有多个键值对时,使用and拼接

  • 只有一个键值对时
1
2
3
4
5
6
7
@Test
public void testDeleteByMap() {
Map<String, Object> map = new HashMap();
map.put("name","E");
int result = userMapper.deleteByMap(map);
System.out.println(result);
}
  • 结果

image-20210129153341026

  • 传入多个键值对时
1
2
3
4
5
6
7
8
@Test
public void testDeleteByMaps() {
Map<String, Object> map = new HashMap();
map.put("name","小明");
map.put("age",18);
int result = userMapper.deleteByMap(map);
System.out.println(result);
}
  • 结果

image-20210129153354773

3.7、配置逻辑删除

逻辑删除:在数据库中没有被移除,只是使用一个变量来使这一条记录失效

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

管理员可以查看被删除的记录,类似于回收站

3.7.1、配置步骤

在表中添加一个deleted字段,

image-20210129153422780

在实体类中添加一个deleted字段,并添加注解

1
2
3
4
5
6
/***
* 逻辑删除字段
* 添加一个逻辑删除注解
*/
@TableLogic
private Integer deleted;

配置逻辑删除组件

1
2
3
4
5
//配置逻辑删除组件
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}

在application.yml文件中配置

1
2
3
4
5
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
  • 当deleted值为1时,证明该数据被逻辑删除
  • 当deleted值为0时,证明该数据没有被逻辑删除

3.7.2、测试逻辑删除

先在数据库中新插入几条数据,以便后面的测试

  • 逻辑删除id为3L的数据
1
2
3
4
@Test
public void testLoginDeleted() {
int result = userMapper.deleteById(3L);
}
  • 结果:使用了update语句

image-20210129153433435

四、性能分析插件

我们在平时开发中,会遇到一些慢sql,mp提供了一个性能分析插件,如果超过指定时间,就停止运行

4.1、作用

性能分析拦截器,用于输出每条sql语句及其执行时间

4.2、使用

在application.yml中配置开发环境,将当前环境设置为dev

1
2
3
spring:
profiles:
active: dev

在配置类中配置sql执行效率分析插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***
* sql执行效率分析插件
* @Profile({"dev","test"})表示此插件只在生产和测试环境下使用
*/
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
//设置sql执行的最大时间,如果超过这个时间就不执行
performanceInterceptor.setMaxTime(1);
//设置格式化SQL语句(美化)
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}

4.3、测试

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testUpdateAndSelect() {
User user = new User();
user.setId(1L);
user.setName("芜湖");
user.setEmail("wuhu@qq.com");
user.setAge(1222);
int result = userMapper.updateById(user);

System.out.println(result);
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out :: println);
}
  • 结果–报告该sql超时

image-20210129153444986

将最大时间设置为100ms,再次测试,修改 performanceInterceptor.setMaxTime(100);

  • 结果

image-20210129153458241

五、条件构造器Wrapper

Wrapper是一个接口,我们使用Wrapper的实现类:QueryWrapper来实现条件构造

5.1、QueryWrapper的一些方法

5.1.1、isNotNull(“列名”)

这个字段的值不为空

5.1.2、ge/eq/ne/le/gt/lt(“列名”,值)

这个字段的值必须大于等于/等于/不等于/小于等于/严格大于/严格小于传入的值

5.1.3、between(“列名”,左边值,右边值)

这个属性的值必须在左边值和右边值之间

5.1.4、notLike(“列名”,值)

字段值 not like “%值%”

5.1.5、likeLeft/likeRight(“列名”,值)

字段 like “%值”/“值%”

5.1.6、in/notIn(“列名”,Object …values)

字段 in/notIn(v0,v1…vn)

5.1.7、inSql/noInSql(“列名”,sql语句)

字段 in/notIn (sql语句),例如 inSql/notInSql(“id”,select * from user where id < 3)

等价于id in/notIn (select * from user where id < 3)

5.1.8、分组排序

  • groupBy(R… columns); // 等价于 GROUP BY 字段, …, 例: groupBy(“id”, “name”) —> group by id,name
  • orderByAsc(R… columns); // 等价于 ORDER BY 字段, … ASC, 例: orderByAsc(“id”, “name”) —> order by id ASC,name ASC
  • orderByDesc(R… columns); // 等价于 ORDER BY 字段, … DESC, 例: orderByDesc(“id”, “name”) —> order by id DESC,name DESC
  • having(String sqlHaving, Object… params); // 等价于 HAVING ( sql语句 ), 例: having(“sum(age) > {0}”, 11) —> having sum(age) > 11

5.2、查询示例

查询name、email不为空,且年龄大于等于12岁的用户(.isNotNull()、.ge())

1
2
3
4
5
6
7
8
9
10
11
12
/***
* 查询name、email不为空,且年龄大于等于12岁的用户(.isNotNull()、.ge())
*/
@Test
public void testQuestion01() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.isNotNull("email");
wrapper.isNotNull("name");
wrapper.ge("age",12);
List users = userMapper.selectList(wrapper);
users.forEach(user -> System.out.println(user));
}
  • 结果

  • sql语句为:

1
2
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND email IS NOT NULL AND name IS NOT NULL AND age >= ? 
==> Parameters: 12(Integer)

image-20210129153512076

查询name属性等于”小明”的用户

1
2
3
4
5
6
7
8
9
10
/***
* 查询name属性等于"小明"的用户
*/
@Test
public void testQuestion02() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq("name","小明");
List users = userMapper.selectList(wrapper);
users.forEach(user -> System.out.println(user));
}
  • 结果

image-20210129153519861

查询年龄在10-30之间的用户个数

1
2
3
4
5
6
7
8
9
10
/***
* 查询年龄在10-30之间的用户个数
*/
@Test
public void testQuestion03() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.between("age",10,30);
int count = userMapper.selectCount(wrapper);
System.out.println(count);
}
  • 结果

image-20210129153527524

查询id小于等于4且没被逻辑删除的用户

1
2
3
4
5
6
7
8
9
10
11
/***
* 查询id小于等于4且没被逻辑删除的用户
*/
@Test
public void testQuestion04() {
QueryWrapper wrapper = new QueryWrapper();
String inSql = "select id from user where id <= 4";
wrapper.inSql("id",inSql);
List users = userMapper.selectList(wrapper);
users.forEach(user -> System.out.println(user));
}
  • sql语句为:
1
SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND id IN (select id from user where id <= 4)
  • 结果

image-20210129153535669

通过id进行降序排序

1
2
3
4
5
6
7
8
9
10
/***
* 查询所有用户,并根据id进行降序排序
*/
@Test
public void testQuestion05() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.orderByDesc("id");
List users = userMapper.selectList(wrapper);
users.forEach(user -> System.out.println(user));
}
  • 结果

image-20210129153544738

六、代码生成器

6.1、介绍

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

6.2、使用

6.2.1、引入依赖

代码生成器需要使用模板引擎,这里使用velocity模板引擎

1
2
3
4
5
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>

配置需要生成对于后台的数据库,这里以leyou_shop数据库的user表为例,生成后台代码

6.2.2、编写代码自动生成器CodeAutoCreator类

这里以leyou_shop库的spu表为例

  • 表结构如下

image-20210129153552969

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
71
72
73
import com.baomidou.mybatisplus.annotation.DbType;
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.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;

/**
* @author 蔡大头
* @title: CodeAutoGenerator
* @projectName mybatis-plus-blog
* @description: TODO
* @date 2020/12/1016:47
*/
public class CodeAutoGenerator {
@Test
public void generator() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("E:\\java\\blog\\src\\main\\java");
gc.setAuthor("蔡大头");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.AUTO); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式

mpg.setGlobalConfig(gc);

// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/leyou_shop?serverTimezone=UTC");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("tianxin1230.");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);

// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.hzx");
pc.setModuleName("mpblog"); //模块名
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);

// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("spu");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀

strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符

mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}

6.3、测试及说明

生成路径、主键策略

image-20210129153604973

设置包名和模块名

image-20210129153612043

设置要生成的表

image-20210129153620219

启动程序,查看结果

image-20210129153637898

Mybatis-plus只对mybatis做增强,不做修改,所以Mybatis有的功能,MP均能实现,对于一些复杂的查询,可以使用写xml文件的方式来完成。