mysql 自增長通用單號生成
阿新 • • 發佈:2018-11-28
平時工作中我們經常會生成各種單號,大部分的單號都是日期加上自增長的序列如:VC20181115001,VC201811151525001,常用格式: 字母 + yyyyMMdd + 001,字母 + yyyyMMddHHmmss + 001等等。
我們可以使用mysql解決這個問題,使用儲存過程呼叫,適合普通單號生成,不適合高併發的單號生成。
1.我們新建一張序列表 sys_sequence
CREATE TABLE `sys_sequence` ( `name` varchar(32) NOT NULL, `value` int(10) DEFAULT NULL, `step` smallint(5) DEFAULT NULL, `start` int(10) DEFAULT NULL, PRIMARY KEY (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
name 欄位為我們設定的字母標識,value 欄位為當前的序列號,step為每次增長的數字大小,start為起始數字
2.我們新建一個儲存過程來呼叫生成序列,也可以用程式碼
CREATE PROCEDURE `generateSeq`(
IN m VARCHAR(100),OUT n INTEGER
)
BEGIN
DECLARE t_error INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
START TRANSACTION;
SET @v:= (SELECT EXISTS (SELECT `value` FROM `sys_sequence` WHERE `name`=m));
SET @m=0;
IF(@v=0) THEN
INSERT INTO `sys_sequence`(`name`,`value`,`step`,`start`) VALUE(m,(SELECT @m:=1),1,1);
ELSE
UPDATE `sys_sequence` SET `value` [email protected]:=`value`+1 WHERE `name`=m;
END IF;
SET [email protected];
IF t_error =1 THEN
ROLLBACK;
SET n = -1;
ELSE
COMMIT;
END IF;
SELECT n ;
END
儲存過程一個入參 name,一個出參n
首先根據傳入的引數name查詢出當前的序列值value,做個判斷如果這個value值等於0則表示是第一次生成序列號,則預設即將生成的序列號為1,自增長為1,如果value值不等0則表示不是第一次生成序列號,則更新當前獲取的序列號value值加1,最後在返回生成的序列號。
3.程式碼呼叫
我們可以用mybatis程式碼生成器生成表 sys_sequence 的程式碼,然後放進專案裡,這裡步驟省略。
SequenceService程式碼:
@Service
public class SequenceService {
@Autowired
private SequenceExMapper sequenceExMapper
//使用儲存過程事物控制
@Transactional(readOnly = false, propagation = Propagation.NOT_SUPPORTED)
public int getSeq(String name){
Sequence sq = new Sequence();
sq.setName(name);
int value = sequenceExMapper.getSeq(sq);
return value;
}
}
SequenceExMapper程式碼:
@Repository
public interface SequenceExMapper {
int getSeq(Sequence sequence);
}
SequenceExMapper.xml 程式碼:
<select id="getSeq" statementType="CALLABLE" resultType="INTEGER">
{ CALL generateSeq(
#{name,jdbcType=VARCHAR,mode=IN},
#{value,jdbcType=INTEGER,mode=OUT})
}
</select >
Sequence 物件程式碼:
public class Sequence implements Serializable{
private static final long serialVersionUID = 1L;
private java.lang.String name;//
private java.lang.Integer value;//
private Short step;//
private java.lang.Integer start;//
// 省略get和set方法
}
我們在需要生成單號的地方呼叫 SequenceService的getSeq方法即可,注意這個方法返回的只是一個當前的序列號數字如5,如果想要005這樣的就需要我們再次拼接一下。
新建一個 CertificationService 程式碼:
@Service
public class CertificationService {
private static Logger logger = LoggerFactory.getLogger(CertificationService.class);
@Autowired
private SequenceService sequenceService;
/**
* 獲取編碼,格式如 VC20181115001
* @return
*/
public String getSeqDateNo() {
int seqNo = sequenceService.getSeq("VC");
String suffixCode = String.format("%03d", seqNo);
String currentDate = DateUtil.getDateStringCompact(new Date());
String certificationNo = "VC" + currentDate + suffixCode;
return certificationNo;
}
/**
* 獲取編碼,格式如 VC201811151525001
* @return
*/
public String getSeqDateTimeNo() {
int seqNo = sequenceService.getSeq("VC");
String suffixCode = String.format("%03d", seqNo);
String currentDate = DateUtil.getDateTimeString4(new Date());
String certificationNo = "VC" + currentDate + suffixCode;
return certificationNo;
}
}
DateUtil的程式碼點選檢視