公司內部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)
);