网页设计网站名称网址提交
1. IKeyGenerator主键生成
内置实现类,缺少mysql,因为mysql不支持序列,只能通过表模拟序列
H2KeyGenerator
PostgreKeyGenerator
KingbaseKeyGenerator 人大金仓的KES数据库
DB2KeyGenerator
OracleKeyGenerator
2. 新建表模拟序列
CREATE TABLE `dual_sequence` (`sequence_key` varchar(100) NOT NULL COMMENT '序列key(主键)',`step` int NOT NULL DEFAULT '1' COMMENT '步长',`start_value` bigint NOT NULL DEFAULT '0' COMMENT '开始值',`end_value` bigint DEFAULT NULL COMMENT '结束值',`ver` int DEFAULT NULL COMMENT '版本号',PRIMARY KEY (`sequence_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='临时序列表 '--添加一条记录
INSERT INTO dual_sequence
(sequence_key, step, start_value, end_value, ver)
VALUES('next.dbid', 1, 0, NULL, 0);
3.代码实现
MysqlKeyGenerator类
package com.yl.mybatisplus.plugin;import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.yl.mybatisplus.mp.entity.DualSequence;
import com.yl.mybatisplus.mp.mapper.DualSequenceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MysqlKeyGenerator implements IKeyGenerator {@Autowiredprivate DualSequenceMapper dualNextMapper;/*** 执行sql** @param incrementerName 序列名称(对应类上注解 {@link KeySequence#value()} 的值)* @return*/@Overridepublic String executeSql(String incrementerName) {// 先查询悲观锁,再修改乐观锁 保证查询的是最新的,如果更新失败,再次获取最新的DualSequence dualSequence = dualNextMapper.selectById("next.dbid");Long startValue = dualSequence.getStartValue();int number = dualNextMapper.updateById(dualSequence);//如果更新失败,再次执行查询获取最新的if (number == 0) {return executeSql(incrementerName);}//更新后的是最新的起始值作为idreturn String.valueOf(startValue+dualSequence.getStep());}
}
其他类
package com.yl.mybatisplus.mp.entity;import lombok.Data;/*** 临时序列** @author liuxubo* @date 2023/8/10 10:27*/
@Data
public class DualSequence {private String sequenceKey;private Integer step;private Long startValue;private Long endValue;private Long ver;
}package com.yl.mybatisplus.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yl.mybatisplus.mp.entity.DualSequence;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;/*** <p>* 临时序列表 Mapper 接口* </p>** @author admin* @since 2021-03-27*/
@Mapper
public interface DualSequenceMapper extends BaseMapper<DualSequence> {/*** 使用悲观锁,防止查询时,其他线程修改** @param sequenceKey* @return*/@Select("select * from dual_sequence where sequence_key=#{sequenceKey} for update")DualSequence selectById(String sequenceKey);/*** 使用版本号修改** @param dualSequence 临时序列* @return*/@Update("update dual_sequence set start_value=start_value+step, ver=ver+1 where sequence_key=#{sequenceKey} and ver=#{ver}")int updateById(DualSequence dualSequence);
}
package com.yl.mybatisplus.mp.controller;import com.yl.mybatisplus.plugin.MysqlKeyGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 临时序列** @author liuxubo* @date 2023/8/10 10:54*/
@RestController
@RequestMapping("/sequence")
public class DualSequenceController {@Autowiredprivate MysqlKeyGenerator mysqlKeyGenerator;@GetMapping("/nextId")public String nextId(){return mysqlKeyGenerator.executeSql(null);}}