MyBatis實(shí)現(xiàn)主鍵返回功能的幾種方式
引言
在 MyBatis 中,當(dāng)我們執(zhí)行插入操作后,經(jīng)常需要獲取數(shù)據(jù)庫(kù)生成的主鍵值(如自增ID、序列值等)。MyBatis 提供了幾種方式來(lái)實(shí)現(xiàn)主鍵返回功能。
一、主要應(yīng)用場(chǎng)景
- 插入數(shù)據(jù)后需要立即使用生成的主鍵
- 需要將主鍵值用于后續(xù)業(yè)務(wù)邏輯或關(guān)聯(lián)操作
- 需要返回完整對(duì)象(包含主鍵)給前端
二、核心實(shí)現(xiàn)方式
1. 使用 useGeneratedKeys 和 keyProperty(推薦)
這是最常用的方式,適用于支持自動(dòng)生成主鍵的數(shù)據(jù)庫(kù)(如 MySQL、SQL Server)。
XML 配置方式
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (username, email, age)
VALUES (#{username}, #{email}, #{age})
</insert>
注解配置方式
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{{age})")
int insertUser(User user);
2. 使用 <selectKey> 元素
這種方式更靈活,適用于所有數(shù)據(jù)庫(kù),特別是那些不支持自動(dòng)生成主鍵的數(shù)據(jù)庫(kù)(如 Oracle)。
MySQL 示例
<insert id="insertUser" parameterType="User">
<selectKey keyProperty="id" resultType="java.lang.Long" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username, email, age)
VALUES (#{username}, #{email}, #{age})
</insert>
Oracle 示例
<insert id="insertUser" parameterType="User">
<selectKey keyProperty="id" resultType="java.lang.Long" order="BEFORE">
SELECT user_seq.NEXTVAL FROM DUAL
</selectKey>
INSERT INTO user (id, username, email, age)
VALUES (#{id}, #{username}, #{email}, #{age})
</insert>
3. 注解方式使用 @SelectKey
@Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{age})")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id",
resultType = Long.class, before = false)
int insertUser(User user);
三、屬性詳解
1. useGeneratedKeys
- 作用:告訴 MyBatis 使用 JDBC 的
getGeneratedKeys方法來(lái)取出由數(shù)據(jù)庫(kù)內(nèi)部生成的主鍵 - 取值:true|false
- 默認(rèn)值:false
2. keyProperty
- 作用:指定能夠唯一識(shí)別對(duì)象的屬性(即主鍵字段)
- 注意:如果是復(fù)合主鍵,可以用逗號(hào)分隔多個(gè)屬性名
3. keyColumn
- 作用:設(shè)置生成鍵值在表中的列名
- 注意:某些數(shù)據(jù)庫(kù)(如 PostgreSQL)必須指定,但大部分情況下 MyBatis 可以自動(dòng)識(shí)別
4. <selectKey> 屬性
keyProperty:指定主鍵字段對(duì)應(yīng)的屬性名resultType:主鍵的類型order:執(zhí)行順序,BEFORE|AFTERBEFORE:先獲取主鍵,再執(zhí)行插入語(yǔ)句AFTER:先執(zhí)行插入語(yǔ)句,再獲取主鍵
四、使用示例
實(shí)體類
public class User {
private Long id;
private String username;
private String email;
private Integer age;
// 構(gòu)造方法、getter、setter 省略
}
Mapper 接口
public interface UserMapper {
int insertUser(User user);
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{age})")
int insertUserWithAnnotation(User user);
}
測(cè)試代碼
// 獲取 SqlSession 和 Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 創(chuàng)建用戶對(duì)象
User user = new User();
user.setUsername("john_doe");
user.setEmail("john@example.com");
user.setAge(25);
// 執(zhí)行插入操作
int result = userMapper.insertUser(user);
// 插入成功后,主鍵會(huì)自動(dòng)回填到 user 對(duì)象中
System.out.println("插入成功,生成的主鍵ID: " + user.getId());
// 此時(shí)可以直接使用 user.getId() 進(jìn)行后續(xù)操作
五、不同數(shù)據(jù)庫(kù)的注意事項(xiàng)
MySQL
- 使用
useGeneratedKeys="true"或SELECT LAST_INSERT_ID() - 表必須具有自增主鍵
Oracle
- 需要使用序列(Sequence)
- 通常使用
order="BEFORE"
PostgreSQL
- 使用
useGeneratedKeys="true" - 可能需要指定
keyColumn
SQL Server
- 使用
useGeneratedKeys="true" - 也可以使用
SELECT SCOPE_IDENTITY()
六、最佳實(shí)踐
- 推薦使用
useGeneratedKeys:代碼更簡(jiǎn)潔,性能更好 - 明確指定
keyProperty:避免因?qū)傩悦灰恢聦?dǎo)致的問(wèn)題 - 考慮使用
keyColumn:當(dāng)數(shù)據(jù)庫(kù)列名與對(duì)象屬性名不一致時(shí)特別有用 - 測(cè)試多種情況:特別是批量插入時(shí)的主鍵返回行為
- 處理復(fù)合主鍵:如果需要返回多個(gè)生成的值,可以用逗號(hào)分隔多個(gè)屬性名
<!-- 復(fù)合主鍵示例 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id,version">
INSERT INTO user (...) VALUES (...)
</insert>
七、常見(jiàn)問(wèn)題解決
主鍵沒(méi)有回填到對(duì)象中
- 檢查
keyProperty是否與實(shí)體類的屬性名一致 - 檢查數(shù)據(jù)庫(kù)是否確實(shí)生成了主鍵
批量插入時(shí)主鍵返回
- 某些數(shù)據(jù)庫(kù)可能只返回最后一個(gè)插入的主鍵
- 考慮使用
<foreach>結(jié)合<selectKey>實(shí)現(xiàn)批量主鍵返回
通過(guò)合理使用 MyBatis 的主鍵返回功能,可以大大簡(jiǎn)化代碼并提高開(kāi)發(fā)效率。
到此這篇關(guān)于MyBatis實(shí)現(xiàn)主鍵返回功能的幾種方式的文章就介紹到這了,更多相關(guān)MyBatis主鍵返回攻略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
數(shù)據(jù)同步利器DataX簡(jiǎn)介及如何使用
DataX?是阿里云?DataWorks數(shù)據(jù)集成?的開(kāi)源版本,使用Java?語(yǔ)言編寫(xiě),在阿里巴巴集團(tuán)內(nèi)被廣泛使用的離線數(shù)據(jù)同步工具/平臺(tái),今天給大家分享一個(gè)阿里開(kāi)源的數(shù)據(jù)同步工具DataX,在Github擁有14.8k的star,非常受歡迎2024-02-02
Java實(shí)現(xiàn)Excel圖片URL篩選與大小檢測(cè)的全過(guò)程
在數(shù)據(jù)處理場(chǎng)景中,我們常需篩選Excel中的圖片URL,本文分享一個(gè)完整的Java方案,涵蓋從讀取圖片URL到檢測(cè)有效性、篩選大小,再到生成新Excel文件的全過(guò)程,同時(shí)講解開(kāi)發(fā)與優(yōu)化過(guò)程,需要的朋友可以參考下2025-08-08
Struts2實(shí)現(xiàn)單文件或多文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Struts2實(shí)現(xiàn)單文件或多文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Java數(shù)據(jù)結(jié)構(gòu)(線性表)詳解
本文主要介紹了Java數(shù)據(jù)結(jié)構(gòu)(線性表)的相關(guān)知識(shí)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
HttpClient實(shí)現(xiàn)遠(yuǎn)程調(diào)用
這篇文章主要為大家詳細(xì)介紹了HttpClient實(shí)現(xiàn)遠(yuǎn)程調(diào)用的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
Java JVM字節(jié)碼指令集總結(jié)整理與介紹
本節(jié)將會(huì)著重介紹一下JVM中的指令集、Java是如何跨平臺(tái)的、JVM指令集參考手冊(cè)等內(nèi)容。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
SpringBoot基于Mybatis攔截器和JSqlParser實(shí)現(xiàn)數(shù)據(jù)隔離
本文將介紹如何在 Spring Boot 項(xiàng)目中利用Mybatis的強(qiáng)大攔截器機(jī)制結(jié)合JSqlParser,一個(gè)功能豐富的 SQL 解析器,來(lái)輕松實(shí)現(xiàn)數(shù)據(jù)隔離的目標(biāo),本文根據(jù)示例展示如何根據(jù)當(dāng)前的運(yùn)行環(huán)境來(lái)實(shí)現(xiàn)數(shù)據(jù)隔離,需要的朋友可以參考下2024-04-04

