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

关于REPEATABLE_READ保证特定值唯一性及代码正确性的技术问询

问题2:上述伪代码是否可满足该需求?

同样不能。

这段代码的逻辑是「先检查再插入」,但这两步不是原子操作:

  • 在高并发场景下,多个请求会同时通过existsByHeight的检查,然后各自执行插入,最终产生重复数据。
  • 哪怕加上了REPEATABLE_READ隔离级别,也改变不了「检查和插入是两个独立操作」的事实,竞态条件依然存在。

如何正确实现身高唯一的需求?

要彻底解决这个问题,必须结合数据库底层约束和代码逻辑:

  1. 给Height字段添加数据库唯一约束
    这是最可靠的底层保障,不管应用层代码有没有漏洞,数据库都会直接拒绝重复插入:
ALTER TABLE Human ADD CONSTRAINT unique_human_height UNIQUE (Height);
  1. 代码中捕获唯一约束冲突异常
    当数据库抛出唯一约束违反的异常(比如SQLIntegrityConstraintViolationException)时,将其转换为你的业务异常HumanWithSuchHeightExists即可。
  2. 可选:用悲观锁优化并发场景
    如果并发量较高,想在应用层提前拦截重复请求,可以在检查时使用「排他锁」锁定查询范围,确保同一时间只有一个事务能执行插入:
@Autowired HumanRepository humanRepo;

@Transactional(isolationLevel = REPEATABLE_READ)
void addHuman(int height){
    // 自定义JPQL:SELECT COUNT(h) > 0 FROM Human h WHERE h.height = :height FOR UPDATE
    boolean exists = humanRepo.existsByHeightForUpdate(height);
    if(exists){
        throw new HumanWithSuchHeightExists();
    }
    humanRepo.save(Human.builder().height(height).build());
}

这里的existsByHeightForUpdate需要在HumanRepository中自定义查询方法,通过FOR UPDATE语句锁定对应的记录范围,避免并发竞态。


内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:24