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

MyBatis 插入資料自動回寫主鍵 ID 完整指南

     編輯:Java 相關知識

核心屬性:useGeneratedKeys + keyProperty

MyBatis 透過 JDBC 的 `Statement.getGeneratedKeys()` 取得資料庫自增主鍵,並自動回寫到實體或 Map 的指定屬性中。

XML 映射檔配置

<insert id="insertOrder" useGeneratedKeys="true" keyProperty="id" 
        parameterType="com.example.model.Orders">
    insert into orders
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="number != null">order_number,</if>
        <if test="orderTime != null">order_time,</if>
    </trim>
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="number != null">#{number},</if>
        <if test="orderTime != null">#{orderTime},</if>
    </trim>
</insert>

Mapper 介面定義

public interface OrderMapper {
    /** 回傳值為影響行數,主鍵已回寫到 order 物件的 id 欄位 */
    int insertOrder(Orders order);
}

實體類別

public class Orders {
    private Long id;      // 自增主鍵,插入後自動回寫
    private String number;
    private Date orderTime;
    // getter/setter 省略
}

服務層調用與驗證

@Service
public class OrderService {
    @Autowired OrderMapper orderMapper;

    public Long createOrder(Orders order) {
        int rows = orderMapper.insertOrder(order);
        if (rows > 0) {
            return order.getId(); // 直接獲取回寫的主鍵
        }
        throw new RuntimeException("插入失敗");
    }
}

Map 參數形式(無實體類別時)

<insert id="insertMap" useGeneratedKeys="true" keyProperty="id" parameterType="map">
    insert into orders (order_number, order_time) values (#{number}, #{orderTime})
</insert>

public int insertMap(Map<String, Object> params);

// 調用
Map<String, Object> params = new HashMap<>();
params.put("number", "ORD-001");
params.put("orderTime", new Date());
mapper.insertMap(params);
Long id = (Long) params.get("id"); // 從 Map 取回主鍵

多主鍵 / 非自增場景:selectKey

若主鍵非自增(如 UUID、序列、複合鍵),改用 ``:

<insert id="insertWithSeq">
    <selectKey keyProperty="id" resultType="long" order="BEFORE">
        select nextval('order_seq')  -- PostgreSQL 序列
        -- select seq_order.nextval from dual  -- Oracle
    </selectKey>
    insert into orders (id, order_number) values (#{id}, #{number})
</insert>

常見坑點與排查

現象原因解決
id 仍為 null資料表主鍵未設 AUTO_INCREMENT檢查 DDL:`id bigint auto_increment primary key`
keyProperty 拼錯實體欄位名不一致(如 `orderId` vs `id`)確保 `keyProperty` 對應實體確切欄位名
批次插入無回寫MyBatis `ExecutorType.BATCH` 不支援 getGeneratedKeys改用 `ExecutorType.SIMPLE` 或逐條插入
PostgreSQL serial 型別需指定 `keyColumn="id"`加上 `keyColumn` 屬性指定主鍵欄位名

原理一覽

  1. MyBatis 建立 `PreparedStatement` 時傳入 `Statement.RETURN_GENERATED_KEYS`
  2. 執行 `executeUpdate()` 後呼叫 `getGeneratedKeys()` 取得 `ResultSet`
  3. 遍歷 `ResultSet`,透過反射將值設定到參數物件的 `keyProperty` 欄位

善用 `useGeneratedKeys`,讓資料庫負責主鍵生成,應用層零負擔獲取 ID,是 MyBatis 最實用的「小而美」功能之一。

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