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

JPARepository.save未检测到SQL Server主键重复异常问题

问题原因分析

你遇到的情况是JPA中JpaRepository.save()方法的默认行为导致的:

  • 调用save()时,JPA会先判断实体的主键是否已存在于数据库中
  • 如果主键已存在,不会执行插入操作,而是执行更新操作,将现有记录的非主键字段替换为新实体的字段值
  • 第二次调用save()时,虽然你创建了新的实体对象,但复合主键(BEGIN_VERSION, END_VERSION)和数据库中已有的记录一致,JPA自动执行了更新而非插入,因此不会触发SQL Server的主键冲突异常
解决方案

如果你希望重复插入同主键记录时触发主键冲突异常(即只允许插入新记录,不允许更新),可以采用以下两种方式:

方式一:先查询再判断

在执行save前,先通过主键查询数据库是否存在对应记录,存在则直接返回失败或抛出异常:

@Transactional(transactionManager = "standardizedDataSourceTransactionManager", propagation = Propagation.REQUIRES_NEW)
public boolean processSave(long beginVersion, long endVersion, String hostId) {
    boolean success = false;
    try {
        TableFlattenProcessingInfoCPK cpk = new TableFlattenProcessingInfoCPK(beginVersion, endVersion);
        // 先查询是否存在该主键的记录
        if (flattenProcessingInfoRepo.existsById(cpk)) {
            log.info("Batch already taken up for processing");
            return false;
        }
        TableFlattenProcessingInfo tableFlattenProcessingInfo = new TableFlattenProcessingInfo();
        tableFlattenProcessingInfo.setTableFlattenProcessingInfoCPK(cpk);
        tableFlattenProcessingInfo.setHostId(hostId);
        tableFlattenProcessingInfo.setProcessingDateTime(DateUtil.convertUTCToEST(new Date(),
                TimeZone.getTimeZone("UTC"),
                TimeZone.getTimeZone("America/New_York")));
        flattenProcessingInfoRepo.save(tableFlattenProcessingInfo);
        success = true;
    } catch (Exception e) {
        log.info("Error Inserting Flatten Batch -> {}", e.getMessage());
        success = false;
    }
    return success;
}

方式二:使用EntityManager.persist()强制插入

persist()方法只负责插入新实体,如果主键已存在会直接抛出EntityExistsException,不会执行更新:

@Autowired
private EntityManager entityManager;

@Transactional(transactionManager = "standardizedDataSourceTransactionManager", propagation = Propagation.REQUIRES_NEW)
public boolean processSave(long beginVersion, long endVersion, String hostId) {
    boolean success = false;
    try {
        TableFlattenProcessingInfoCPK cpk = new TableFlattenProcessingInfoCPK(beginVersion, endVersion);
        TableFlattenProcessingInfo tableFlattenProcessingInfo = new TableFlattenProcessingInfo();
        tableFlattenProcessingInfo.setTableFlattenProcessingInfoCPK(cpk);
        tableFlattenProcessingInfo.setHostId(hostId);
        tableFlattenProcessingInfo.setProcessingDateTime(DateUtil.convertUTCToEST(new Date(),
                TimeZone.getTimeZone("UTC"),
                TimeZone.getTimeZone("America/New_York")));
        // 使用persist强制插入
        entityManager.persist(tableFlattenProcessingInfo);
        success = true;
    } catch (EntityExistsException e) {
        log.info("Batch already taken up for processing by another Pod -> {}", e.getMessage());
        success = false;
    } catch (Exception e) {
        log.info("Error Inserting Flatten Batch -> {}", e.getMessage());
        success = false;
    }
    return success;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:43:16