如何解决从另一个实体(JPA)继承的实体的“未指定主键”?

Posted

技术标签:

【中文标题】如何解决从另一个实体(JPA)继承的实体的“未指定主键”?【英文标题】:How to solve 'no primary key specified' for an Entity that inherits from another Entity (JPA)? 【发布时间】:2016-04-08 21:09:40 【问题描述】:

我想要一个对所有文档类型都通用的超类:

@Entity
public abstract class Doc implements Serializable


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected long docId;

    public long getDocId()
    
        return docId;
    

    public void setDocId(long docId)
    
        this.docId = docId;
    


我想为每种文档类型创建子类:

@Entity
@Table(name = "DocTypeA")
public class DocTypeA extends Doc implements Serializable

    // other child fields

但它给出了一个错误并说 DocTypeA 需要一个主键。如何隔离主键并将其放在超类中?因为所有的子类都会有相同的 id 字段。

我正在使用 EclipseLink。

我的另一个问题是:为什么我需要将@Entity 放在抽象类中?作为一个抽象类,它不能被实例化,那么将它标记为实体有什么意义呢?真的有必要吗?我不会坚持超类。我只需要它来隔离所有子类中通用的代码。

堆栈跟踪很长,相关部分粘贴在下面:

Exception Description: Entity class [class repository.DocTypeA] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.

【问题讨论】:

准确和完整的错误堆栈跟踪是什么?您希望您的数据库架构是什么样的? 当您遇到该异常时,您确定 Doc 类确实用 @Entity 进行了注释吗? 阅读***.com/questions/9667703/… 【参考方案1】:

根据official JavaDoc注解@MappedSuperclass

指定一个类,其映射信息应用于从它继承的实体。映射的超类没有为其定义单独的表。

这就是你要找的。因此abstract 类可以很容易地用于实体的公共属性,在大多数情况下,主键或数据库生成的对象标识符就是。该抽象类的注释字段将只映射到具体的子类:

使用MappedSuperclass 注释指定的类可以以与实体相同的方式映射,除了映射仅适用于其子类,因为映射的超类本身不存在表。当应用于子类时,继承的映射将应用于子类表的上下文中。

像这样交换抽象类Doc中的@Entity注解:

@MappedSuperclass
public abstract class Doc implements Serializable

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected long docId;
    //...

你应该很高兴。

希望对你有帮助。

【讨论】:

以上是关于如何解决从另一个实体(JPA)继承的实体的“未指定主键”?的主要内容,如果未能解决你的问题,请参考以下文章

JPA实体继承实体的映射策略

JPA实体继承实体的映射策略

Jpa实体VO使用继承的实体的做法@MappedSuperclass注解的使用

传递给持久化的分离实体:JPA 继承

EclipseLink + JPA + 通用实体 + SINGLE_TABLE 继承

spring-data-jpa实体类继承抽象类如何映射父类的属性到数据库