Spring Data JPA使用@MappedSuperclass继承主键后实体报无主键错误
错误原因及修复方案
报错由两个配置问题导致:
- 复合主键类
IndexId未实现JPA规范强制要求的equals()和hashCode()方法,JPA底层需要通过这两个方法判断实体主键的唯一性,缺失对应实现会被识别为无效主键结构。同时主键类需要显式声明无参构造方法。 @IdClass注解配置位置错误,该注解配置在子类实体上,但主键字段全部定义在@MappedSuperclass标注的基类中,注解放到基类上才能被所有继承的子类正确复用。
调整后的代码示例
1. 修正后的主键类IndexId
import java.io.Serializable; import java.util.Objects; public class IndexId implements Serializable { private int seqNo; private String index; // 显式声明无参构造 public IndexId() {} // 可选:增加全参构造方便初始化 public IndexId(int seqNo, String index) { this.seqNo = seqNo; this.index = index; } // 重写equals方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; IndexId indexId = (IndexId) o; return seqNo == indexId.seqNo && Objects.equals(index, indexId.index); } // 重写hashCode方法 @Override public int hashCode() { return Objects.hash(seqNo, index); } // getters and setters }
2. 修正后的基类BaseIndex
import javax.persistence.IdClass; import javax.persistence.MappedSuperclass; import javax.persistence.Id; import javax.persistence.Column; // 将@IdClass注解移到基类,所有继承的子类自动复用主键配置 @MappedSuperclass @IdClass(IndexId.class) public class BaseIndex { @Id @Column(name = "seq_no", nullable = false) protected int seqNo; @Id @Column(name = "index", nullable = false) protected String index; @Column(name = "value", nullable = false) protected String value; // getters/setters }
3. 修正后的实体子类
import javax.persistence.Entity; import javax.persistence.Table; import java.io.Serializable; @Entity @Table(name = "bibliographic_single_index") public class BibliographicSingleIndex extends BaseIndex implements Serializable { }
补充说明
如果项目使用Lombok,可直接在IndexId类上加@Data注解,自动生成无参构造、equals、hashCode和get/set方法,无需手动编写上述重复代码。
内容的提问来源于stack exchange,提问作者André Luiz
相关产品推荐
相关产品推荐

