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

JOOQ中除dslContext.lastID()外,获取最后插入记录ID的可靠替代方法?

并发安全的插入ID获取方案

1. 用returning()直接获取当前插入的ID

这是最靠谱的方案,它会在同一条插入语句中返回当前记录的主键ID,完全不会被其他并发插入操作干扰。修改后的代码如下:

// 执行插入并同步拿到生成的主键ID
Long generatedId = dslContext.insertInto(table(name), field("email"), field("password"))
        .values("test@mail.com", "password")
        .returning(field("id")) // 指定返回主键字段
        .fetchOne()
        .getValue(field("id"));

// 生成你需要的唯一标识
String uniqueCode = "ABCD-" + generatedId;
// 后续可使用该标识更新对应字段,或在插入时直接生成(若数据库支持)

不管是MySQL的自增主键,还是PostgreSQL的序列主键,JOOQ的returning()都会自动适配数据库的返回机制,确保拿到的就是本次插入的ID,与其他线程的插入操作完全隔离。

2. 直接在数据库端生成唯一标识(无需单独获取ID)

如果你的数据库支持函数拼接,可以在插入语句中直接生成ABCD-lastId格式的标识,一步完成插入操作,彻底避免后续获取ID的并发问题。以MySQL为例:

// MySQL示例:插入时直接生成unique_code字段
dslContext.insertInto(table(name), field("email"), field("password"), field("unique_code"))
        .values("test@mail.com", "password", concat("ABCD-", lastInsertId()))
        .execute();

这种方式所有操作都在一条数据库语句中完成,不存在并发冲突,效率也更高。

3. 用事务包裹插入和ID获取(兜底方案)

如果因特殊限制无法使用returning(),可以将插入和ID获取操作放在同一个事务中,确保lastID()拿到的是当前事务内插入的ID(大部分数据库支持事务级别的LAST_INSERT_ID):

dslContext.transaction(config -> {
    DSLContext ctx = DSL.using(config);
    ctx.insertInto(table(name), field("email"), field("password"))
            .values("test@mail.com", "password")
            .execute();
    Long generatedId = ctx.lastID();
    String uniqueCode = "ABCD-" + generatedId;
    // 更新对应的标识字段
    ctx.update(table(name))
            .set(field("unique_code"), uniqueCode)
            .where(field("id").eq(generatedId))
            .execute();
});

不过该方案多了一次更新操作,效率不如前两种,仅作为兜底选择。


内容的提问来源于stack exchange,提问作者Muhamed Risvan M S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:03:24