知識庫 / Spring / Spring Boot RSS 訂閱

使用 MyBatis 和 Spring 從插入操作返回自動生成的 ID

Persistence,Spring Boot
HongKong
6
11:12 AM · Dec 06 ,2025

1. 概述

MyBatis 是一個開源的 Java 持久性框架,可作為 JDBC 和 Hibernate 的替代方案使用。它幫助我們減少代碼,簡化結果檢索,使我們能夠專注於編寫自定義 SQL 查詢或存儲過程。

在本教程中,我們將學習如何插入數據時返回自動生成的 ID,同時結合 MyBatis 和 Spring Boot。

2. 依賴配置

在開始之前,讓我們在 <em/>pom.xml</em/> 中添加mybatis-spring-boot-starter</em/>` 依賴:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

3. 示例設置

我們先創建一個簡單的示例,將在本文檔中反覆使用。

3.1. 定義實體

首先,讓我們創建一個簡單的實體類,表示一輛汽車:

public class Car {
    private Long id;

    private String model;

    // getters and setters
}

第二,我們定義一個創建表並將其放在 car-schema.sql 文件的 SQL 語句:

CREATE TABLE IF NOT EXISTS CAR
(
    ID    INTEGER PRIMARY KEY AUTO_INCREMENT,
    MODEL VARCHAR(100) NOT NULL
);

3.2. 定義 DataSource

接下來,我們將指定一個數據源。我們將使用嵌入式 H2 數據庫:

@Bean
public DataSource dataSource() {
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    return builder
      .setType(EmbeddedDatabaseType.H2)
      .setName("testdb")
      .addScript("car-schema.sql")
      .build();
}

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource());
    return factoryBean.getObject();
}

現在我們已經完成了所有設置,接下來我們將探討如何使用基於標註和基於XML的方法來檢索自動生成的身份。

4. 使用註釋

讓我們定義 Mapper,它代表 MyBatis 使用的方法與對應 SQL 語句進行綁定的接口:

@Mapper
public interface CarMapper {
    // ...
}

接下來,我們添加一個 insert 語句:

@Insert("INSERT INTO CAR(MODEL) values (#{model})")
void save(Car car);

直覺上,我們可能會傾向於直接返回 Long 類型的值,並期望 MyBatis 返回創建的實體的 ID。然而,這種做法並不準確。如果這樣做,它會返回 1,表明 insert 語句已成功執行。

要檢索生成的 ID,我們可以使用 @Options 註解或 @SelectKey 註解。

4.1. @Options 註解

通過使用 @Options 註解,我們可以擴展我們的語句。

@Insert("INSERT INTO CAR(MODEL) values (#{model})")
@Options(useGeneratedKeys = true, keyColumn = "ID", keyProperty = "id")
void saveUsingOptions(Car car);

在這裏,我們設置了三個屬性:

  • useGeneratedKeys – 指示是否使用自動生成鍵功能
  • keyColumn – 設置鍵值存儲在的列名
  • keyProperty – 表示鍵值將存儲在的字段名

此外,我們可以通過用逗號分隔來指定多個鍵屬性。

在後台,MyBatis 使用反射將 ID 列的值映射到 id 字段中 Car 對象的 id 字段

接下來,讓我們創建一個測試以確認一切都按預期工作:

@Test
void givenCar_whenSaveUsingOptions_thenReturnId() {
    Car car = new Car();
    car.setModel("BMW");

    carMapper.saveUsingOptions(car);

    assertNotNull(car.getId());
}

4.2. @SelectKey 註解

使用 @SelectKey 註解返回 ID 還有另一種方式。<strong>此註解在我們需要使用序列或身份函數來檢索標識符時非常有用。</strong>

此外,如果我們在方法上裝飾了 @SelectKey 註解,MyBatis 會忽略諸如 @Options 之類的註解。

讓我們在 CarMapper 中創建一個新方法,以在插入後檢索一個標識符值:

@Insert("INSERT INTO CAR(MODEL) values (#{model})")
@SelectKey(statement = "CALL IDENTITY()", before = false, keyColumn = "ID", keyProperty = "id", resultType = Long.class)
void saveUsingSelectKey(Car car);

讓我們來審視我們使用的屬性:

  • statement – 用於存儲將在執行後執行的語句,該語句在 insert 語句之後執行
  • before – 指示語句應在 insert 語句之前執行還是之後執行
  • keyColumn – 存儲表示鍵的列的名稱
  • keyProperty – 指定用於存儲語句返回的值的字段的名稱
  • resultType – 表示 keyProperty 的類型

此外,請注意 IDENTITY() 函數已從 H2 數據庫中移除。 更多詳細信息可以在 這裏 找到。

為了能夠在 H2 數據庫上執行 CALL IDENTITY(),我們需要將模式設置為 LEGACY:

"testdb;MODE=LEGACY"

讓我們測試我們的方法以確認其正常工作:

@Test
void givenCar_whenSaveUsingSelectKey_thenReturnId() {
    Car car = new Car();
    car.setModel("BMW");

    carMapper.saveUsingSelectKey(car);

    assertNotNull(car.getId());
}

5. 使用 XML

讓我們看看如何實現相同的功能,但這次我們將使用基於 XML 的方法。

首先,讓我們定義 CarXmlMapper 接口:

@Mapper
public interface CarXmlMapper {
     // ...
}

與基於標註的方法不同,我們不會直接在 Mapper 接口中編寫 SQL 語句。相反,我們將定義 XML mapper 文件並將所有查詢都放在其中:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="com.baeldung.mybatis.generatedid.CarXmlMapper">

</mapper>

此外,在 namespace 屬性中,我們指定了 CarXmlMapper 接口的完全限定名稱。

5.1. UseGeneratedKeys 屬性

接下來,我們將在 CarXmlMapper 接口中定義一個方法:

void saveUsingOptions(Car car);

此外,讓我們使用 XML mapper 定義 insert 語句並將其映射到我們放置在 CarXmlMapper 接口中的 saveUsingOptions() 方法:

<insert id="saveUsingOptions" parameterType="com.baeldung.mybatis.generatedid.Car"
  useGeneratedKeys="true" keyColumn="ID" keyProperty="id">
    INSERT INTO CAR(MODEL)
    VALUES (#{model});
</insert>

讓我們來探索我們使用的屬性:

  • id – 將查詢綁定到 CarXmlMapper 類中的特定方法
  • parameterTypesaveUsingOptions() 方法的參數類型
  • useGeneratedKeys – 指示我們想要使用生成的 ID 功能
  • keyColumn – 指定表示鍵的列名
  • keyProperty – 指定 Car 對象中將存儲鍵的字段名稱

此外,讓我們測試我們的解決方案:

@Test
void givenCar_whenSaveUsingOptions_thenReturnId() {
    Car car = new Car();
    car.setModel("BMW");

    carXmlMapper.saveUsingOptions(car);

    assertNotNull(car.getId());
}

5.2. <em>SelectKey</em> 元素

接下來,讓我們在 <em>CarXmlMapper</em> 接口中添加一個新方法,以查看如何使用 <em>SelectKey</em> 元素檢索身份:

void saveUsingSelectKey(Car car);

此外,我們還需要指定 XML 映射器文件中語句並將其綁定到方法上:

<insert id="saveUsingSelectKey" parameterType="com.baeldung.mybatis.generatedid.Car">
    INSERT INTO CAR(MODEL)
    VALUES (#{model});

    <selectKey resultType="Long" order="AFTER" keyColumn="ID" keyProperty="id">
        CALL IDENTITY()
    </selectKey>
</insert>

在這裏,我們定義了 selectKey 元素,使用了以下屬性:

  • resultType – 指定語句返回的結果類型
  • order – 指示語句 CALL IDENTITY() 應在 insert 語句之前或之後調用
  • keyColumn – 存儲標識符的列名
  • keyProperty – 存儲鍵應映射到的字段名

最後,我們創建一個測試:

@Test
void givenCar_whenSaveUsingSelectKey_thenReturnId() {
    Car car = new Car();
    car.setModel("BMW");

    carXmlMapper.saveUsingSelectKey(car);

    assertNotNull(car.getId());
}

6. 結論

在本文中,我們學習瞭如何使用 MyBatis 和 Spring 從 <em >insert</em> 語句中檢索自動生成的 ID。

總結一下,我們探討了如何使用基於註解的方法以及 <em >@Options</em><em >@SelectKey</em> 註解來檢索 ID。此外,我們還研究瞭如何使用基於 XML 的方法返回 ID。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.