1 回答

TA貢獻(xiàn)1995條經(jīng)驗(yàn) 獲得超2個(gè)贊
項(xiàng)目應(yīng)用中,曾有以下一個(gè)場(chǎng)景:
接口中要求發(fā)送一個(gè)int類型的流水號(hào),由于多線程模式,如果用時(shí)間戳,可能會(huì)有重復(fù)的情況(當(dāng)然概率很小)。
所以想到了利用一個(gè)獨(dú)立的自增的sequence來解決該問題。
當(dāng)前數(shù)據(jù)庫(kù)為:mysql
由于mysql和oracle不太一樣,不支持直接的sequence,所以需要?jiǎng)?chuàng)建一張table來模擬sequence的功能,理由sql語(yǔ)句如下:
第一步:創(chuàng)建--Sequence 管理表
Java代碼
DROP TABLE IF EXISTS sequence;
CREATE TABLE sequence (
name VARCHAR(50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 1,
PRIMARY KEY (name)
) ENGINE=InnoDB;
第二步:創(chuàng)建--取當(dāng)前值的函數(shù)
Java代碼
DROP FUNCTION IF EXISTS currval;
DELIMITER $
CREATE FUNCTION currval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE value INTEGER;
SET value = 0;
SELECT current_value INTO value
FROM sequence
WHERE name = seq_name;
RETURN value;
END
$
DELIMITER ;
第三步:創(chuàng)建--取下一個(gè)值的函數(shù)
Java代碼
DROP FUNCTION IF EXISTS nextval;
DELIMITER $
CREATE FUNCTION nextval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
UPDATE sequence
SET current_value = current_value + increment
WHERE name = seq_name;
RETURN currval(seq_name);
END
$
DELIMITER ;
第四步:創(chuàng)建--更新當(dāng)前值的函數(shù)
Java代碼
DROP FUNCTION IF EXISTS setval;
DELIMITER $
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
UPDATE sequence
SET current_value = value
WHERE name = seq_name;
RETURN currval(seq_name);
END
$
DELIMITER ;
第五步:測(cè)試函數(shù)功能
當(dāng)上述四步完成后,可以用以下數(shù)據(jù)設(shè)置需要?jiǎng)?chuàng)建的sequence名稱以及設(shè)置初始值和獲取當(dāng)前值和下一個(gè)值。
INSERT INTO sequence VALUES ('TestSeq', 0, 1);----添加一個(gè)sequence名稱和初始值,以及自增幅度
SELECT SETVAL('TestSeq', 10);---設(shè)置指定sequence的初始值
SELECT CURRVAL('TestSeq');--查詢指定sequence的當(dāng)前值
SELECT NEXTVAL('TestSeq');--查詢指定sequence的下一個(gè)值
在java代碼中,可直接創(chuàng)建sql語(yǔ)句查詢下一個(gè)值,這樣就解決了流水號(hào)唯一的問題。
貼出部分代碼(已測(cè)試通過)
Java代碼
public void testGetSequence() {
Connection conn = JDBCUtils.getConnection(url, userName, password);
String sql = "SELECT CURRVAL('TestSeq');";
PreparedStatement ptmt = null;
ResultSet rs = null;
try {
ptmt = conn.prepareStatement(sql);
rs = ptmt.executeQuery();
int count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, ptmt, conn);
}
}
ps:在應(yīng)用中,還有一種用java代碼去實(shí)現(xiàn)模擬自增sequence的方式,具體思路是創(chuàng)建一張存放sequence的table,然后通過java調(diào)用sql語(yǔ)句去查詢和修改這個(gè)table中指定sequence名稱的值,這種方式請(qǐng)加上synchronized。具體代碼這里就不上傳了,因?yàn)閷?shí)現(xiàn)了,未去測(cè)試過。
添加回答
舉報(bào)