所以我正在使用 DerbyDB 并且正在设置一些实体。我有一个
@MappedSuperclass
,它用作某些实体的超类 (@Entity
)。更具体地说,我有一个超类 User
和 3 个子类,即 admin
、regular
和 guest
。现在我有一个不同的实体,假设 file
应该引用(作为其字段之一)其所有者。所以我创建了一个名为 User owner
的字段。
我得到的错误是:
Exception Description: [File] uses a non-entity [User] as target entity in the relationship attribute [field owner].
有解决办法吗?
@MappedSupperclass
与 @Inheritance
注释不同。
@MappedSuperclass
告诉 JPA 提供程序包含基类持久属性,就好像它们是由扩展用 @MappedSuperclass
注释的超类的子类声明的一样。
但是,继承仅在 OOP 世界中可见,因为从数据库的角度来看,没有基类的指示。只有子类实体才会有关联的映射表。
@Inheritance
注解的目的是在数据库表结构中具体化OOP继承模型。此外,您可以查询用 @Inheritance
注解的基类,但不能对用 @MappedSuperclass
注解的基类执行此操作。
我可以建议两种解决方案:
您得到的异常清楚地描述了您的问题:
User
不是一个实体。任何使用接口 @MappedSuperclass
声明为超类的类都不能是实体 (在标准 JPA 中 - 取决于您的 JPA 提供者)...让我向您指出我刚刚针对类似问题给出的答案
--> 超类类型
因此,将您的超类定义为抽象实体将为您提供所需的行为,如您所描述的。
如果您选择继承映射策略为
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
,您甚至不需要多个数据库表。这是一个很好的例子:JPA 单表继承
不要仅根据角色将用户实体拆分为多个实体。使用您想要的所有角色创建一个
Enum
并将其作为字段添加到您的 User
实体中。这更常见,除非您需要您的管理员、访客等成为自己的对象...
有时为了继承子类,我们创建一个父类,但我们不将其用作表。继承该父类,我们创建各种表。这就是为什么我们不在父类中使用@Entity。而不是我们在父类或超类中使用@MappedSuperClass。