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

MyBatis 獲取 MySQL 自增主鍵:useGeneratedKeys 與 selectKey 兩大方案

     編輯:Java 相關知識

MyBatis 插入數據後獲取 MySQL 自增主鍵:兩種核心方案完整指南

在 MyBatis 中插入數據後獲取資料庫生成的自增主鍵(ID),是極高頻的實戰需求。本文詳細解析 useGeneratedKeys 與 selectKey 兩大方案的配置、原理、適用場景與避坑指南。

方案一:useGeneratedKeys + keyProperty(推薦,標準 JDBC 方式)

Mapper XML 配置



    INSERT INTO spares(spares_name, spares_type_id, spares_spec)
    VALUES(#{name}, #{typeId}, #{spec})

關鍵屬性解析

  • useGeneratedKeys="true":啟用 JDBC 3.0 Statement.getGeneratedKeys() 機制
  • keyProperty="id":將生成的主鍵值回填到實體對象的 id 屬性
  • keyColumn(可選):指定資料庫主鍵列名,複合主鍵或列名不同時需設定

實體類要求


public class Spares {
    private Long id;           // 必須有 setter
    private String name;
    private Integer typeId;
    private String spec;
    // getter/setter
}

Service 調用與獲取


@Service
public class SparesServiceImpl implements SparesService {
    @Autowired
    private SparesMapper sparesMapper;

    @Override
    public int insert(Spares spares) {
        int count = sparesMapper.insert(spares);
        // 插入後,spares.getId() 即可獲取自增主鍵!
        System.out.println("新增記錄 ID: " + spares.getId());
        return count;
    }
}

執行流程

  1. MyBatis 創建 PreparedStatement,設定 Statement.RETURN_GENERATED_KEYS
  2. 執行 executeUpdate()
  3. 調用 getGeneratedKeys() 獲取 ResultSet
  4. 遍歷 ResultSet,將值通過反射設入實體的 keyProperty 屬性

方案二:selectKey 子元素(通用、支援非自增/複雜主鍵)

Mapper XML 配置



    
        SELECT LAST_INSERT_ID()
    
    INSERT INTO person(name, pswd) VALUES(#{name}, #{pswd})

關鍵屬性解析

  • keyProperty="id":回填目標屬性
  • resultType="long":主鍵值類型
  • order="AFTER":插入後執行(MySQL 自增必須 AFTER)
  • order="BEFORE":插入前執行(適用於序列、UUID 等預先生成主鍵)

MySQL 專用函數

  • LAST_INSERT_ID():返回當前連接最後生成的 AUTO_INCREMENT 值,連接級隔離,並發安全
  • SELECT @@IDENTITY:同 LAST_INSERT_ID(),但部分場景不同

兩方案深度對比

維度useGeneratedKeysselectKey (LAST_INSERT_ID)
底層機制JDBC 3.0 標準 API額外 SQL 查詢
資料庫相關性支援多種 DB(需驅動支援)MySQL 專用語法
效能單次往返,略優額外查詢,微小開銷
複合主鍵支援(keyColumn 指定多列)需多次 selectKey
非自增主鍵不支援支援(BEFORE + 序列/UUID)
Oracle/PostgreSQL支援(Sequence + BEFORE)支援(序列 nextval)
批量插入獲取 ID支援(MyBatis 3.4+)不直接支援

進階場景與避坑指南

1. 批量插入獲取多個自增 ID



    INSERT INTO spares(name, type_id, spec) VALUES
    
        (#{item.name}, #{item.typeId}, #{item.spec})
    

要求:MyBatis 3.4.0+、MySQL 5.1.35+ 驅動、rewriteBatchedStatements=true 連接參數。

2. 主鍵非 id 或類型非 Long




    
        SELECT REPLACE(UUID(), '-', '')
    
    INSERT INTO orders(order_no, ...) VALUES(#{orderNo}, ...)

3. 常見錯誤與解決

4. Spring Boot 整合配置


# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db?useGeneratedKeys=true&rewriteBatchedStatements=true
    driver-class-name: com.mysql.cj.jdbc.Driver

最佳實踐建議

  1. MySQL 自增主鍵首選 useGeneratedKeys:標準、高效、可移植
  2. 非自增/跨資料庫/複雜主鍵用 selectKey:靈活可控
  3. 實體類必須有對應屬性的 setter,否則回填失敗
  4. 批量插入場景:驗證驅動版本與連接參數,測試並發正確性
  5. 業務代碼勿依賴 ID 連續性:自增 ID 因回滾、重啟會有間隙

掌握這兩大方案的核心差異與適用邊界,能讓你在任何資料庫主鍵生成場景下遊刃有餘,避免「插入成功但拿不到 ID」的低級錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
現象原因解決
ID 為 0/null未配置 useGeneratedKeys 或 keyProperty 錯誤檢查屬性名、setter 存在性
批量插入 ID 全相同驅動版本低或未開啟 rewriteBatchedStatements升級驅動、加連接參數
並發下 ID 錯誤使用 MAX(id)+1 等非原子方式必須用自增/序列/LAST_INSERT_ID
事務回滾 ID 不連續自增計數器不回滾(資料庫特性)正常現象,業務勿依賴 ID 連續