简介
MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
快速开始
参照官网快速开始的样例,官网用的是h2数据库,我这里用的是Mysql。
-
创建数据库
schema,并执行以下脚本。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'); -
添加依赖
主要的依赖。
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency>测试依赖如下。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <!--单元测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> -
创建一个实体类
package com.yw.pojo; import lombok.Data; @Data public class User { private Long id; private String name; private Integer age; private String email; } -
创建Mapper接口
package com.yw.Mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yw.pojo.User; import org.springframework.stereotype.Repository; @Repository public interface UserMapper extends BaseMapper<User> {} -
配置数据源和日志
# 配置MySQL spring: datasource: username: root password: password url: jdbc:mysql://localhost:3306/schema?userUnicode=true&characterEncoding=utf-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver # 配置日志,以便更好查看结果 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -
添加扫描Mapper文件的注解
package com.yw; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.yw.Mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } -
测试类
package com.yw; import com.yw.Mapper.UserMapper; import com.yw.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest class DemoApplicationTests { @Autowired private UserMapper userMapper; @Test public void testSelect() { List<User> userList = userMapper.selectList(null); System.out.println(userList); } }
然后就完成了。这的确比mybatis简单了不少。
mybatis大概流程是导入依赖,定义实体类,定义mapper接口,创建绑定mapper接口的xml配置文件,配置数据源并绑定mybatis的配置文件和实体类,然后才能使用。现在简单了很多。
主键生成策略
雪花算法
主键生成策略有很多,不过主要学习一下这个雪花算法。
首先来做个插入的测试。
package com.yw;
import com.yw.Mapper.UserMapper;
import com.yw.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Autowired
private UserMapper userMapper;
//用的还是官网给的测试数据库
@Test
public void testInsert() {
User user = new User();
user.setAge(20);
user.setEmail("1141950370@qq.com");
user.setName("yww");
userMapper.insert(user);
}
}
这个测试是没有设置主键id的值的,来看一下主键的生成。
插入成功之后看到数据是这样的。

这么一长串的id是什么东西呢,我们在官网看到主键有个注释@TableId,点进去看看源码。
package com.baomidou.mybatisplus.annotation;
import java.lang.annotation.*;
/**
* 表主键标识
*
* @author hubin
* @since 2016-01-23
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
/**
* 字段名(该值可无)
*/
String value() default "";
/**
* 主键类型
* {@link IdType}
*/
IdType type() default IdType.NONE;
}
这里就可以看到主键是可以可无的,下面是默认的主键生成策略,我们在点IdType进去看看有什么策略。
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* 生成ID类型枚举类
*
* @author hubin
* @since 2015-11-10
*/
@Getter
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),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_ID}
*/
@Deprecated
ID_WORKER(3),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_ID}
*/
@Deprecated
ID_WORKER_STR(3),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_UUID}
*/
@Deprecated
UUID(4);
private final int key;
IdType(int key) {
this.key = key;
}
}
在这里就看到当主键为空的时候,会有一个默认的生成策略ASSIGN_ID,这个策略的默认实现算法是雪花算法。

总结
官网已经将上述方法已经总结的很好了,我就直接放官方的表了。
| 值 | 描述 |
|---|---|
| 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方法) |
分布式全局唯一ID 长整型类型(please use ASSIGN_ID) | |
32位UUID字符串(please use ASSIGN_UUID) | |
分布式全局唯一ID 字符串类型(please use ASSIGN_ID) |
从官网的删除线和源码来看,后面三种是已经不支持使用了的。
默认的生成策略是NONE,相当于INPUT,就是自己设置主键的值,当主键没有设值的时候,默认是使用ASSIGN_ID雪花算法。
代码生成器
首先需要引入依赖。
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<!-- 代码生成器的引擎 velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
引擎可以选择其他的,这里就使用velocity。
这里给出一个比较通用的配置。
想要更加自定义的配置可以参考代码生成器的配置文档
https://baomidou.com/pages/981406/
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.fill.Column;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
/**
* <p>
* MyBatisPlus的代码生成器
* </p>
*
* @ClassName CodeGenerator
* @Author yww
* @Date 2022/10/8 16:26
*/
public class CodeGenerator {
/**
* 获取配置文件application.yml中关于mysql的配置
* @return 数据库配置
*/
@NotNull
@Contract(" -> new")
private static DataSourceConfig.Builder getDataSourceConfig() {
// 配置文件为application.yml使用
YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
factoryBean.setResources(new ClassPathResource("application.yml"));
Properties properties = factoryBean.getObject();
if (properties == null) {
throw new RuntimeException("请确认配置文件是否名为application.yml,是否在resources资源目录下!");
}
String url = (String) properties.get("spring.datasource.url");
String username = (String) properties.get("spring.datasource.username");
String password = (String) properties.get("spring.datasource.password");
if (url == null || url.isEmpty()) {
throw new RuntimeException("mysql的url出错!");
}
if (username == null || username.isEmpty()) {
throw new RuntimeException("mysql的username出错!");
}
if (password == null || password.isEmpty()) {
throw new RuntimeException("mysql的password出错!");
}
return new DataSourceConfig.Builder(url, username, password);
}
/**
* 执行 run
*/
public static void main(String[] args) {
// 项目路径 + /src/main
String path = System.getProperty("user.dir").replaceAll("\\\\","/") + "/src/main";
FastAutoGenerator.create(getDataSourceConfig())
// 全局配置
.globalConfig(builder -> builder
// 作者名称
.author("yww")
// 指定输出目录
.outputDir(path + "/java")
// 禁止打开输出目录
.disableOpenDir()
// 时间策略
.dateType(DateType.TIME_PACK)
// 注释日期
.commentDate("yyyy-MM-dd")
// 开启springdoc的注解
.enableSpringdoc()
.build()
)
// 包配置
.packageConfig(builder -> builder
// 父包名
.parent("com.yww.management")
.build()
)
// 模板配置
.templateConfig(builder -> builder
// 禁用所有模板
//.disable()
.controller(path + "/resources/templates/controller.java.vm")
.build())
// 策略配置
.strategyConfig((scanner, builder) -> builder
// 增加表匹配
.addInclude(getTables(scanner.apply("请输入表名,如需输入多个表名,可用英文逗号分隔,选择所有表输入all")))
// controller策略
.controllerBuilder().enableRestStyle().enableHyphenStyle()
// entity策略配置
.entityBuilder().enableLombok()
.idType(IdType.ASSIGN_ID)
.enableTableFieldAnnotation()
.addTableFills(new Column("create_time", FieldFill.INSERT))
.addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE))
.build()
)
.execute();
}
/**
* 处理输入all的情况
*/
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}