mybatis-plus实现mysql自定义IKeyGenerator

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 {
    @Autowired
    private DualSequenceMapper dualNextMapper;

    /**
     * 执行sql
     *
     * @param incrementerName 序列名称(对应类上注解 {@link KeySequence#value()} 的值)
     * @return
     */
    @Override
    public 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);
        }

        //更新后的是最新的起始值作为id
        return 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;

/**
 * 

* 临时序列表 Mapper 接口 *

* * @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 { @Autowired private MysqlKeyGenerator mysqlKeyGenerator; @GetMapping("/nextId") public String nextId(){ return mysqlKeyGenerator.executeSql(null); } }

你可能感兴趣的:(mybatis,mysql,数据库)