Mybatis-Plus主键生成策略详解

简介: Mybatis-Plus主键生成策略详解

前言


很多人在使用Mybatis-Plus的时候可能会疑惑,自己明明没有配置主键的生成策略,但是执行新增操作时却自动生成了主键,而且还特别长。这是由于Mybatis-Plus默认就会采用雪花算法填充主键字段。


今天就和大家详解聊聊Mybatis-Plus中主键生成的相关策略。


一、官网


Mybatis-Plus主键策略:https://baomidou.com/pages/e131bd/


Mybatis-Plus自定义ID生成器:https://baomidou.com/pages/568eb2/


TIP⚠️:

推荐学习框架的时候,多研究下官网,获取第一手资料。


二、主键注解@TableId说明


1、源码

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
    String value() default "";
    IdType type() default IdType.NONE;
}

30.png


2、作用

标识主键字段

使用@TableId可以标识实体对象中和数据库表中主键对应的字段。如果不添加@TableId注解,会默认匹配id字段为主键。


变量名称和主键字段名称的匹配

如果表中的主键字段名称和实体中的主键字段名称不相同,这时候就要通过@TableId中的value属性明确指出对应的数据库主键字段的名称。


指定主键的生成方式

可以通过@TableId注解中的type属性指定主键的生成策略,具体支持哪些策略可以在IdType枚举中查看。


3、使用

@TableName(value ="user")
@Data
public class User implements Serializable {
    /**
     * 主键ID
     */
    @TableId(value = "id",type = IdType.ASSIGN_ID)
    private Long userId;
    private String name;
    private Integer age;
    private String email;


三、主键生成策略-IdType枚举说明


通过查看IdType枚举类的源码,可以发现Mybatis-Plus中默认支持5种主键生成方式。


1、源码

public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4);
    private final int key;
    private IdType(int key) {
        this.key = key;
    }
    public int getKey() {
        return this.key;
    }
}


2、说明

描述

AUTO

数据库 ID自增,这种情况下将表中主键设置为自增,否则,没有设置主动设置id值进行插入时会报错

NONE

无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里默认 ASSIGN_ID),注意这里官网文档有误

INPUT

insert 前自行 set 主键值,在采用IKeyGenerator类型的ID生成器时必须为INPUT

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 方法)


3、全局设置

IdType默认的全局设置为IdType.ASSIGN_ID,即由mybatis-plus主动分配主键,默认情况下由默认主键生成器实现类DefaultIdentifierGenerator采用雪花算法填充主键。

public DbConfig() {
    this.idType = IdType.ASSIGN_ID;
    this.tableUnderline = true;
    this.capitalMode = false;
    this.logicDeleteValue = "1";
    this.logicNotDeleteValue = "0";
    this.insertStrategy = FieldStrategy.NOT_NULL;
    this.updateStrategy = FieldStrategy.NOT_NULL;
    this.whereStrategy = FieldStrategy.NOT_NULL;
}

在spring boot中,可以通过如下配置更改全局配置。

mybatis-plus.global-config.db-config.id-type=assign_id


三、ID生成器介绍


Mybatis-Plus中的ID生成器主要分为2类,一类是IdentifierGenerator,另一类是IKeyGenerator。

29.png


1、IdentifierGenerator

源码如下:

public interface IdentifierGenerator {
    //根据id是否为null判断是否需要主动分配Id
    default boolean assignId(Object idValue) {
        return StringUtils.checkValNull(idValue);
    }
    //生成数值型Id
    Number nextId(Object entity);
    //生成字符型uuid
    default String nextUUID(Object entity) {
        return IdWorker.get32UUID();
    }
}


说明:

IdentifierGenerator生成器中主要提供了3个方法。

其使用场景是:不依赖数据库生成ID,而是由mybatis-plus自己提供一套id生成算法。 对应的主键生成方式为IdType.ASSIGN_ID、ASSIGN_UUID。


assignId 是否需要分配id

nextId 获取下一个数值型Id

nextUUID 获取下一个uuid

典型的实现是默认的id生成器DefaultIdentifierGenerator,基于雪花算法生成id。`

public class DefaultIdentifierGenerator implements IdentifierGenerator {
    private final Sequence sequence;
    public DefaultIdentifierGenerator() {
        this.sequence = new Sequence((InetAddress)null);
    }
    public DefaultIdentifierGenerator(InetAddress inetAddress) {
        this.sequence = new Sequence(inetAddress);
    }
    public DefaultIdentifierGenerator(long workerId, long dataCenterId) {
        this.sequence = new Sequence(workerId, dataCenterId);
    }
    public DefaultIdentifierGenerator(Sequence sequence) {
        this.sequence = sequence;
    }
    public Long nextId(Object entity) {
        return this.sequence.nextId();
    }
}


具体使用:

1、声明由mybatis-plus分配主键值

@TableName(value ="user")
@Data
public class User implements Serializable {
    /**
     * 主键ID
     */
    @TableId(value = "id",type = IdType.ASSIGN_ID)
    private Long userId;
    private String name;
    private Integer age;
    private String email;


2、指定idGenerator的实现类

如果是默认的DefaultIdentifierGenerator,则不需要用户重新指定。

@Configuration
public class IdAutoConfig {
    @Value("${mybatis-plus.zookeeper.serverLists}")
    private String zkServerLists;
    @Bean
    public IdentifierGenerator idGenerator() {
        return new ImadcnIdentifierGenerator(zkServerLists);
    }
}


2、IKeyGenerator

源码如下:

public interface IKeyGenerator {
    //执行sql生成id
    String executeSql(String incrementerName);
    //获取数据库类型
    DbType dbType();
}


说明:

IKeyGenerator 生成器主要是根据不同的数据库类型,执行sql语句生成对应的主键。典型的数据库如Oracle,Postgre,需要根据序列器生成表主键。


相关实现类:

28.png

OracleKeyGenerator中的实现:

可以发现,是通过执行sql调用序列器生成的id。

public class OracleKeyGenerator implements IKeyGenerator {
    public OracleKeyGenerator() {
    }
    public String executeSql(String incrementerName) {
        return "SELECT " + incrementerName + ".NEXTVAL FROM DUAL";
    }
    public DbType dbType() {
        return DbType.ORACLE;
    }
}


具体使用:

1、在实体中通过@KeySequence指定序列器名称,并通过@TableId指定主键生成策略为IdType.INPUT

@KeySequence(value = "SEQ_ORACLE_STRING_KEY", clazz = String.class)
public class YourEntity {
    @TableId(value = "ID_STR", type = IdType.INPUT)
    private String idStr;
}


2、spring boot配置列中配置keyGenerator具体实现类


@Bean
public IKeyGenerator keyGenerator() {
    return new OracleKeyGenerator();
}


也可以通过配置项指定:

mybatis-plus.global-config.db-config.key-generators=com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator


四、自定义主键生成器


自定义主键生成器也有2种方式。

如果需要通过执行sql语句来生成id的,可以通过实现IKeyGenerator接口来自定义。 如果不想依赖数据库,完全自定义一套主键生成策略,那么可以通过实现IdentifierGenerator接口来扩展。


下面演示如何通过实现IdentifierGenerator接口,自定义主键生成器。


1、自定义id生成器

@Component
public class CustomIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
        //可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
        String bizKey = entity.getClass().getName();
        //根据bizKey调用分布式ID生成
        long id = ....;
        //返回生成的id值即可.
        return id;
    }
}


2、配置类中指定id生成器


@Bean
public IdentifierGenerator idGenerator() {
    return new CustomIdGenerator();
}


3、实体类中指定主键分配策略IdType.ASSIGN_ID

@TableName(value ="user")
@Data
public class User implements Serializable {
    /**
     * 主键ID
     */
    @TableId(value = "id",type = IdType.ASSIGN_ID)
    private Long userId;
    private String name;
    private Integer age;
    private String email;


总结


本文主要是介绍了Mybatis-Plus主键生成策略及其相关的扩展方法。


1、详细介绍了@TableId注解的属性和作用,推荐项目中在实体的主键字段上明确添加@TableId注解,标识id字段以及id生成策略IdType。


2、目前mybatis-plus中有5种Id生成策略IdType,搞清楚各种的用法和使用场景。


AUTO 数据库 ID自增

NONE 未设置主键类型,也就是跟随全局策略,全局策略默认为ASSIGN_ID

INPUT insert 前自行 set 主键值

ASSIGN_ID 分配 ID

ASSIGN_UUID 分配 UUID

3、Mybatis-Plus中的ID生成器主要分为2类,一类是IdentifierGenerator,另一类是IKeyGenerator,搞清楚他们的区别和各自的使用场景。


IdentifierGenerator 适用于不依赖数据库,用户自定义的主键生成场景。

IKeyGenerator 依赖数据库,通过执行sql语句生成主键的场景。

目录
相关文章
|
1月前
|
Java 数据库连接 mybatis
Mybatis Plus保存数据返回主键id
Mybatis Plus保存数据返回主键id
22 1
|
4月前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
93 0
|
7月前
|
XML Java 数据库连接
【MySQL用法】MyBatis 多对多 中间表插入数据,添加记录后获取主键ID
【MySQL用法】MyBatis 多对多 中间表插入数据,添加记录后获取主键ID
67 0
|
4月前
|
Java 关系型数据库 MySQL
Mybatis和Mybatis-Plus执行插入语句后可以返回主键ID吗?
Mybatis和Mybatis-Plus执行插入语句后可以返回主键ID吗?
56 0
|
5月前
|
算法 数据库
MYSQL-mybatisplus的主键自增问题与@Tableld@TableField@TableLogic的学习
关于org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.laoyang.Mapper.BookMapper.deleteById问题
|
5月前
|
存储 XML Java
Mybatis使用SelectKey自定义主键
Mybatis使用SelectKey自定义主键
65 0
|
6月前
|
SQL 算法 关系型数据库
Mybatis-Plus3.0默认主键策略导致自动生成19位长度主键id的坑
Mybatis-Plus3.0默认主键策略导致自动生成19位长度主键id的坑
25 0
|
6月前
|
数据库
Mybatis-plus插入数据遇到主键没有默认值的问题
Mybatis-plus插入数据遇到主键没有默认值的问题
|
7月前
|
存储 算法 数据库
mybatisPlus主键策略解读
mybatisPlus主键策略解读