首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring JDBC 實現序號產生器:SequenceDaoJdbcImpl 深度解析

     編輯:Java 相關知識

背景與需求

分散式系統常需要全域唯一、有序的序號(如訂單號、流水號)。本文分析 SequenceDaoJdbcImpl,展示如何利用 Spring JdbcTemplate 衍生類實現線程安全的序號分配。

資料庫結構

CREATE TABLE sequence (
    seq_name  VARCHAR(50) PRIMARY KEY,
    seq_value INT NOT NULL
);

核心 SQL 陳述式

SELECT_SQL  = "SELECT seq_name, seq_value FROM sequence WHERE seq_name = ?"
UPDATE_SQL  = "UPDATE sequence SET seq_value = ? WHERE seq_name = ?"
INSERT_SQL  = "INSERT INTO sequence(seq_name, seq_value) VALUES (?, ?)"

關鍵實現細節

1. Spring JDBC 操作物件封裝

三個內部類分別對應查詢、更新、插入:

  • SequenceQuery extends MappingSqlQuery:將 ResultSet 映射為 Sequence 領域物件
  • SequenceUpdate extends SqlUpdate:執行遞增更新
  • SequenceInsert extends SqlUpdate:初始化新序列

2. 序號獲取邏輯:getSequence()

public int getSequence(String seq_name) {
    Object obj = sequenceQuery.findObject(new Object[]{seq_name});
    if (obj == null) {
        sequenceInsert.insert(seq_name, 0);  // 首次使用自動建立
    }
    Sequence seq = (Sequence) sequenceQuery.findObject(new Object[]{seq_name});
    sequenceUpdate.update(seq.getName(), seq.getValue() + 1);
    return seq.getValue() + 1;  // 回傳遞增後的值
}

注意:此實現非原子操作,高併發下可能產生重複序號。生產環境建議:

  • 資料庫層面使用 SELECT ... FOR UPDATE 行鎖
  • 或改用資料庫原生序列(Oracle Sequence、PostgreSQL SERIAL、MySQL AUTO_INCREMENT)
  • 或採用 Redis INCR 指令實現分散式原子計數器

3. 初始化檢查:afterPropertiesSet()

實現 InitializingBean 介面,確保 DataSource 已注入,否則拋出 ApplicationContextException。

領域物件:Sequence

public class Sequence {
    private String name;
    private int value;
    // getter/setter 省略
}

優化建議

  1. 批次預取:一次更新 seq_value += 100,記憶體中快取 100 號段,減少資料庫往返
  2. 樂觀鎖:UPDATE sequence SET seq_value = seq_value + 1 WHERE seq_name = ? AND seq_value = ?,失敗則重試
  3. 雪花演算法:若需全域唯一且趨勢遞增,考慮 Snowflake ID(64-bit: timestamp + workerId + sequence)

總結

SequenceDaoJdbcImpl 展示了 Spring JDBC 操作物件模式的經典用法,代碼結構清晰,但併發安全性需視業務量級加強。現代專案多改用資料庫原生序列或 Redis,簡化開發並提升效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved