前言
在实际开发过程中,数据库自增主键生成Id能满足大部分的场景。
但是随着分布式应用场景的增多,表数据的增大导致分表分库的大量应用。
数据库自增主键的生成规则无法满足对应的业务场景,于是诞生了越来越多的分布式ID生成算法,其中雪花算法是目前最为流行的。
今天说一下在mybatis-plus中如何使用雪花算法生成Id。
一、mybatis-plus官网
Git地址:https://github.com/baomidou/mybatis-plus
TIP⚠️:
推荐学习框架的使用的时候,都多研究下官网,获取第一手资料。
二、雪花算法实战
1.建表
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)
);
注意⚠️:
这里的主键字段没有配置自增生成策略,所以执行新增操作的时候,需要给id字段设置值,才能新增成功。类似如下:
INSERT INTO user ( id, name, age, email ) VALUES ( 123434, 'test', 13, '101@qq.com')
2.新建测试工程
相关代码:
maven依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
实体User:
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
mapper:
public interface UserMapper extends BaseMapper<User> {
}
启动类Application:
@SpringBootApplication
@Slf4j
@MapperScan("com.laowan.mybatis_plus.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
log.info("mybatis_plus_demo 启动成功");
}
}
注意⚠️:
这里在启动类上配置了@MapperScan(“mapper接口目录”),所以在UserMapper接口上没有条件@Mapper注解。
@Mapper配置方法:
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
两者任意选择一种方式配置即可,如果都不配置,那么在执行dao层方法进行数据操作时,会出现在spring容器中找不到对应的bean的异常。
@Mapper和@MapperScan都不配置调用mapper方法时出现的异常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.laowan.mybatis_plus.mapper.UserMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
配置属性:
server.port=8080
logging.level.com.laowan.mybatis_plus.mapper=debug
spring.datasource.url = jdbc:mysql://localst:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.datasource.username = root
spring.datasource.password = 123456
3.测试
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
System.out.println(("----- insert method test ------"));
User user = new User();
user.setName("test");
user.setAge(13);
user.setEmail("101@qq.com");
userMapper.insert(user);
System.out.println(user.toString());
}
执行结果:
User(id=728666272023183375, name=test, age=13, email=101@qq.com)
多次执行,发现主键ID的确呈趋势递增。
结论:
主键id的生成策略已经采用了雪花算法,呈趋势递增。
三、实现分析
很多人可能疑惑🤔,你这明明啥都没干,怎么就实现了雪花算法生成Id。
其实mybatis-plus已经内置雪花算法生成分布式唯一id。
在mybatis-plus特性中已经明确说明了这点。
我们可以直接在IDEA中双击shift搜索Sequence类查看其具体实现,可以发现其实现就是采用了雪花算法。
四、为什么默认就是雪花算法
实体User:
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
这里可以看到我们并没有在实体类的id上设置id生成策略。
其实mybatis-plus中默认的主键生成策略为DefaultIdentifierGenerator
,里面的实现就是采用Sequence生成主键。
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();
}
}
五、主动设置Id生成策略
可以通过mybatis-plus中的@TableId
主键,主动标识主键字段,并配置主键生成策略。
@Data
public class User {
//采用IdentifierGenerator默认的实现类DefaultIdentifierGenerator生成id
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private Integer age;
private String email;
}
总结
mybatis-plus已经内置了雪花算法生成分布式唯一Id,并且是默认的ID生成策略。
大家在实际项目中,可以通过在主键字段上添加@TableId注解来控制主键的生成策略。