文章目录
MyBatis主键回填机制深度解析:useGeneratedKeys
与<selectKey>
的选择与实践
一、引言:主键回填的价值与场景
在数据库操作中,插入数据后获取生成的主键(如自增ID、序列值等)是常见的需求。例如,电商订单生成后需立即获取订单号进行支付关联。MyBatis提供了两种核心机制实现主键回填:
useGeneratedKeys
+keyProperty
+keyColumn
:基于JDBC驱动的自动生成键能力<selectKey>
标签:通过自定义SQL灵活获取主键
本文将深入解析这两种方案的使用场景、配置细节及最佳实践。
二、自动生成键配置:useGeneratedKeys
三件套
- 属性解析
属性 | 作用 | 示例值 |
---|---|---|
useGeneratedKeys | 启用数据库自动生成键回填(如MySQL的AUTO_INCREMENT ) | true /false |
keyProperty | 指定Java对象中接收主键值的属性名 | "userId" |
keyColumn | 数据库表中生成主键的列名(用于属性与列名不一致时映射) | "USER_ID" |
- 协作流程
<insert id="insertUser" useGeneratedKeys="true"
keyProperty="userId" keyColumn="USER_ID">
INSERT INTO user (name) VALUES (#{name})
</insert>
-
执行顺序:
- 插入数据 → 2. 数据库生成主键 → 3. MyBatis通过JDBC接口获取键值 → 4. 回填至
keyProperty
指定属性
- 插入数据 → 2. 数据库生成主键 → 3. MyBatis通过JDBC接口获取键值 → 4. 回填至
-
适用数据库:MySQL、SQL Server等支持
AUTO_INCREMENT
或类似特性的数据库。
三、灵活控制:<selectKey>
标签详解
- 核心属性
属性 | 说明 |
---|---|
keyProperty | 接收主键值的Java对象属性名(必填) |
resultType | 主键数据类型(如Long 、String ) |
order | 执行时机:BEFORE (插入前生成主键)或AFTER (插入后获取,如MySQL自增) |
- 典型场景示例
场景1:Oracle序列生成主键(BEFORE)
<insert id="insertDept">
<selectKey keyProperty="deptId" resultType="long" order="BEFORE">
SELECT dept_seq.NEXTVAL FROM dual
</selectKey>
INSERT INTO dept (id, name) VALUES (#{deptId}, #{name})
</insert>
场景2:MySQL自增ID回填(AFTER)
<insert id="insertOrder">
<selectKey keyProperty="productId" resultType="long" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO orders (product_id) VALUES (#{productId})
</insert>
- 优势与适用性
- 多数据库兼容:适配Oracle、PostgreSQL等非自增主键场景
- 复合主键支持:通过一条SQL返回多个字段值(需配合
resultMap
) - 灵活控制逻辑:可调用函数、计算值等复杂主键生成逻辑
四、对比与选型建议
维度 | useGeneratedKeys | <selectKey> |
---|---|---|
实现原理 | 依赖JDBC驱动自动获取 | 自定义SQL查询 |
性能 | 更高效(单次交互) | 需额外SQL执行(BEFORE模式可能增加延迟) |
灵活性 | 仅支持简单自增主键 | 支持序列、函数、多字段等复杂场景 |
数据库兼容性 | 仅限MySQL、SQL Server等 | 全数据库通用 |
代码简洁度 | 配置简单 | 需编写额外SQL |
选型建议:
- 优先
useGeneratedKeys
:适用于MySQL等自增主键场景,代码简洁高效。 - 必须用
<selectKey>
的情况:- Oracle、PostgreSQL等使用序列
- 多主键或自定义主键生成逻辑
- 需要兼容多种数据库的工程
五、常见问题与解决方案
- 主键未回填?
- 检查
keyProperty
是否与Java对象属性名一致 - 确认数据库驱动支持自动生成键(如MySQL需使用
AUTO_INCREMENT
)
<selectKey>
执行顺序错误
- Oracle等需
order="BEFORE"
,MySQL自增需order="AFTER"
- 多主键回填
<selectKey keyProperty="id1,id2" resultType="hashmap" order="BEFORE">
SELECT key1_seq.nextval AS id1, key2_seq.nextval AS id2 FROM dual
</selectKey>
- 使用
HashMap
接收多字段,属性名需与键名匹配
六、总结
通过合理选择useGeneratedKeys
或<selectKey>
,开发者可以优雅地实现主键回填。简单场景追求效率,复杂场景拥抱灵活,同时注意数据库兼容性和属性映射的准确性。建议在跨数据库项目中统一使用<selectKey>
以增强可移植性。