mysql 數據庫 自增索引

公司內部mysql數據庫分表自增索引生成工具反編譯代碼實現:
原來是注入datasoure 和使用jdbc 操作數據庫的 現在爲了簡單直接使用mybatis
如果你願意可以改回去 這樣比較通用。

NO BB,show Code.

import java.util.concurrent.atomic.AtomicLong;

@Data
@Slf4j
public class SequenceServiceImpl implements SequenceService {

    private int retryTimes = 2;
    private int innerStep = 1000;

    private SequenceMapper sequenceMapper;
    private String name = "name";
    private volatile SequenceRange currentRange;

    @Override
    public long nextValue() {
        if (this.currentRange == null) {
            synchronized (this) {
                if (this.currentRange == null) {
                    this.currentRange = this.nextRange(this.name);
                }
            }
        }

        long value = this.currentRange.getAndIncrement();
        if (value == -1L) {
            synchronized (this) {
                do {
                    if (this.currentRange.isOver()) {
                        this.currentRange = this.nextRange(this.name);
                    }
                    value = this.currentRange.getAndIncrement();
                } while (value == -1L);
            }
        }

        if (value < 0L) {
            throw new RuntimeException("Sequence value overflow, value = " + value);
        } else {
            return value;
        }
    }

    private SequenceRange nextRange(String name) {
        if (name == null) {
            throw new IllegalArgumentException("序列名稱不能爲空");
        }
        for (int i = 0; i < this.getRetryTimes() + 1; ++i) {
            Long oldValue = sequenceMapper.getCurrentValue(name);
            if (oldValue == null) {
                try {
                    sequenceMapper.addNameCurrentValue(name);
                } catch (Exception e) {
                    log.warn("Sequence value init error", e);
                }
                oldValue = sequenceMapper.getCurrentValue(name);
            }
            if (oldValue == null) {
                throw new RuntimeException("Sequence value init error");
            }
            if (oldValue < 0L) {
                throw new RuntimeException("Sequence value cannot be less than zero");
            }

            if (oldValue > 9223372036754775807L) {
                throw new RuntimeException("Sequence value overflow");
            }

            Long newValue = oldValue + (long) this.getInnerStep();
            int affectedRows = sequenceMapper.updateSeqValue(name, newValue, oldValue);
            if (affectedRows != 0) {
                return new SequenceRange(oldValue + 1L, newValue);
            }
        }
        throw new RuntimeException("Retried too many times, retryTimes = " + this.getRetryTimes());

    }

    @Data
    public static class SequenceRange {
        private final long min;
        private final long max;
        private final AtomicLong value;
        private volatile boolean over = false;

        public SequenceRange(long min, long max) {
            this.min = min;
            this.max = max;
            this.value = new AtomicLong(min);
        }

        public long getAndIncrement() {
            long currentValue = this.value.getAndIncrement();
            if (currentValue > this.max) {
                this.over = true;
                return -1L;
            } else {
                return currentValue;
            }
        }


        public boolean isOver() {
            return this.over;
        }
    }

}

seq mybatis mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.xxxx.dao.SequenceMapper">
    <insert id="addNameCurrentValue">
        INSERT INTO sequence (gmt_create, gmt_modified, name, value, current_value)
         VALUES
         (now(), now(), #{name}, 100000, 100000);
    </insert>
    <select id="getCurrentValue" resultType="java.lang.Long">
        SELECT current_value FROM sequence WHERE name=#{name}
    </select>
    <update id="updateSeqValue">
      update sequence set current_value= #{newValue} where name=#{name} and current_value= #{oldValue}
    </update>
</mapper>

數據庫建表腳本

create table if not exists sequence
(
  id            bigint unsigned auto_increment
  constraint `PRIMARY`
  primary key,
  gmt_create    datetime           null,
  gmt_modified  datetime           null,
  name          varchar(64)        null,
  current_value bigint default '0' null,
  constraint sequence_name_uindex
  unique (name)
);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章