跨資料庫自動增長鍵取得的歷史困境
| 資料庫 | 舊版驅動方案 | 痛點 |
| SQL Server 2000 | INSERT ...; SELECT @@IDENTITY (單陳述式) | MySQL 不支援單陳述式多結果集;併發下 @@IDENTITY 受觸發器干擾 |
| MySQL | executeUpdate() + executeQuery("SELECT LAST_INSERT_ID()") | 兩次往返,併發風險,代碼分支化 |
| 通用 JDBC 3.0 | PreparedStatement.getGeneratedKeys() | SQL Server 2000 驅動**不支援** |
破局:SQL Server 2005 JDBC 驅動 1.1 完整支援 JDBC 3.0
- 下載:
sqljdbc_1.1.1501.101_chs.exe (Microsoft 官方)。
- 核心能力:完整實作
Statement.getGeneratedKeys(),回傳 ResultSet 包含自動增長欄值。
- 統一代碼模式:所有資料庫統一使用
getGeneratedKeys(),消除分支邏輯。
驅動遷移關鍵差異 (2000 → 2005)
| 項目 | SQL Server 2000 驅動 | SQL Server 2005 驅動 (1.1+) |
| JDBC URL | jdbc:microsoft:sqlserver://host:1433;DatabaseName=db;SelectMethod=cursor | jdbc:sqlserver://host:1433;DatabaseName=db;SelectMethod=cursor |
| Driver Class | com.microsoft.jdbc.sqlserver.SQLServerDriver | com.microsoft.sqlserver.jdbc.SQLServerDriver |
| 套件結構 | mssqlserver.jar + msutil.jar + msbase.jar | sqljdbc.jar (單一 JAR) |
| getGeneratedKeys() | ❌ 不支援 | ✅ 完整支援 |
統一實作範本
public Long insertAndGetKey(Connection conn, String sql, Object... params) throws SQLException {
try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
// 綁定參數
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
int affected = ps.executeUpdate();
if (affected == 0) return null;
// 統一取得自動增長鍵
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
// 兼容不同資料庫回傳型別:BigInt/Int/Decimal
return rs.getLong(1);
}
}
return null;
}
}
// 使用範例
Long orderId = insertAndGetKey(conn,
"INSERT INTO Orders (CustomerID, OrderDate, Total) VALUES (?, ?, ?)",
custId, new Date(), totalAmount);
進階注意事項
- 觸發器干擾:SQL Server
@@IDENTITY 受 AFTER INSERT 觸發器插入其他表影響;getGeneratedKeys() 底層使用 SCOPE_IDENTITY(),**免疫觸發器干擾**,更安全。
- 複合主鍵/非 IDENTITY 自增:
getGeneratedKeys() 僅回傳 IDENTITY 欄位;SEQUENCE (2012+) 或 UNIQUEIDENTIFIER 需改用 OUTPUT INSERTED.KeyCol 子句。
- 批次插入:
executeBatch() 後呼叫 getGeneratedKeys() 回傳所有列的鍵值 (JDBC 4.0+),舊版驅動可能僅回傳第一列。
- 連接池配置:確保
maxPoolSize 足夠,避免高併發下等待連接超時(記得 2000 SP4 的教訓)。
驗證清單
- [ ] 專案依賴已更新為
sqljdbc.jar (1.1+),移除舊三個 JAR。
- [ ] 所有資料庫連接 URL 已遷移至
jdbc:sqlserver:// 格式。
- [ ] Driver Class 字串已更新為
com.microsoft.sqlserver.jdbc.SQLServerDriver。
- [ ] 所有插入操作統一使用
prepareStatement(sql, RETURN_GENERATED_KEYS) + getGeneratedKeys()。
- [ ] 整合測試覆蓋 SQL Server 2005/2008/2012、MySQL、PostgreSQL、Oracle (需
RETURN_GENERATED_KEYS + getGeneratedKeys() 配合 INSERT ... RETURNING)。
總結
SQL Server 2005 JDBC 驅動引入 getGeneratedKeys() 支援,終結了跨資料庫自動增長鍵處理的分支地獄。遷移核心在於「換 URL、換 Class、換 JAR、統一代碼」。配合 SCOPE_IDENTITY() 底層語義,比舊式 @@IDENTITY 更安全、更標準、更易維護。