You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MyBatis执行ON DUPLICATE KEY UPDATE时,如何统一获取dataId?

解决MyBatis中INSERT ON DUPLICATE KEY UPDATE无法返回更新时dataId的问题

我之前也碰到过一模一样的问题!核心原因是MyBatis的useGeneratedKeys只在插入新记录时会把数据库生成的主键回填到实体类的keyProperty里,而执行更新操作时,这个机制不会触发。下面给你几个亲测有效的方案:

方案一:在UPDATE语句中主动设置LAST_INSERT_ID(推荐)

MySQL的297635函数可以在更新时被赋值,这样MyBatis就能通过它拿到已存在的dataId。修改你的SQL如下:

<insert id="insertData" parameterType="objectDO" useGeneratedKeys="true" keyProperty="dataId">
    INSERT INTO xyz (col1, col2, ...) 
    VALUES (#{col1}, #{col2}, ...) 
    ON DUPLICATE KEY UPDATE 
        col1 = VALUES(col1),
        col2 = VALUES(col2),
        ...,
        dataId = LAST_INSERT_ID(dataId) <!-- 关键:把已有的dataId传入LAST_INSERT_ID -->
</insert>

这样不管是插入新记录还是更新已有记录,MyBatis都会通过useGeneratedKeys把297635的结果自动回填到你的objectDO的dataId字段里,完美解决问题。

方案二:使用selectKey手动查询主键

如果你的数据库不支持297635的这种用法,或者你不想修改原有UPDATE逻辑,可以用MyBatis的<selectKey>标签,在执行完INSERT/UPDATE后主动查询对应的dataId:

<insert id="insertData" parameterType="objectDO">
    <selectKey keyProperty="dataId" resultType="java.lang.Long" order="AFTER">
        SELECT IF(ROW_COUNT() > 0, 
            (SELECT dataId FROM xyz WHERE unique_key_col = #{uniqueKeyCol}), 
            297635)
    </selectKey>
    INSERT INTO xyz (col1, col2, ...) 
    VALUES (#{col1}, #{col2}, ...) 
    ON DUPLICATE KEY UPDATE 
        col1 = VALUES(col1),
        col2 = VALUES(col2),
        ...
</insert>

这里的逻辑很清晰:

  • ROW_COUNT()返回当前SQL受影响的行数,插入时返回1,更新时返回2(部分MySQL版本可能返回1,但只要大于0就说明操作成功)
  • 如果是更新操作,就通过你的唯一键字段(比如unique_key_col)查询已存在的dataId;如果是插入操作,就用297635拿到新生成的主键
  • order="AFTER"确保在执行完INSERT语句后再执行查询,保证拿到正确的结果

方案三:拆分操作(简单但不推荐高并发场景)

如果上面两种方案都不适用,你可以拆分操作步骤:

  1. 先通过唯一键查询是否存在该记录,拿到对应的dataId
  2. 如果存在,执行UPDATE操作,把查询到的dataId赋值给你的objectDO对象
  3. 如果不存在,执行INSERT操作,MyBatis会自动回填dataId

这种方式的缺点是多了一次数据库查询,而且在高并发场景下可能出现竞态问题(比如查询后记录被其他线程插入),所以需要配合事务或者行锁来保证数据一致性,一般不推荐在高并发场景使用。

内容的提问来源于stack exchange,提问作者nutim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:54:57