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

使用@GeneratedValue(IDENTITY)为何触发Duplicate Key异常?

问题根源分析

你遇到的java.lang.IllegalStateException: Duplicate key异常,核心问题出在实体类的主键配置错误:

  • 你的JobMetadataEntity中,id字段标注了@Id和@GeneratedValue(strategy = GenerationType.IDENTITY),但注释明确说明该字段不是数据库列。
  • GenerationType.IDENTITY策略依赖数据库的自增列生成主键值,而这个字段不在数据库中,JPA无法为它生成唯一标识值。这就导致查询返回的多个实体可能出现相同的id值,最终调用Collectors.toMap时因为键重复抛出异常。
解决方案

1. 修正实体类主键配置(根本解决)

根据实际需求选择以下两种方式:

方式一:id仅作内存标识,无需作为JPA主键

直接移除@Id和@GeneratedValue注解,手动为id生成唯一值:

public class JobMetadataEntity implements Serializable {
    // 仅作为内存标识,不是DB列
    private Integer id;
    @Column(name = "MODULE")
    private String module;

    // 实例化时手动生成唯一id,比如用AtomicInteger自增
    private static final AtomicInteger ID_GENERATOR = new AtomicInteger(0);
    public JobMetadataEntity() {
        this.id = ID_GENERATOR.incrementAndGet();
    }
}

方式二:将id作为数据库主键

如果需要id作为JPA主键,必须让它对应数据库的自增列:

  1. 在数据库中为JobMetadataEntity对应的表添加自增id列(比如MySQL的id INT AUTO_INCREMENT PRIMARY KEY);
  2. 保留实体类的@Id和@GeneratedValue(strategy = GenerationType.IDENTITY)注解,移除“NOT a DB Column”注释:
public class JobMetadataEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "MODULE")
    private String module;
}

2. 临时规避toMap重复键异常(可选)

如果暂时无法修改实体类,可以在collect时指定重复键的处理逻辑,避免抛出异常。比如用新值覆盖旧值:

Map<Integer, JobMetadataEntity> jobMetadataEntityMap = jobMetadataRepository.findAllByModule("MODULE_NAME")
                .stream().collect(Collectors.toMap(e -> e.getId(), e -> e, (oldVal, newVal) -> newVal));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 13:07:40