在 JPA (EclipseLink) 的一个实体中结合 @Embeddable 和 @MappedSuperclass

Combining @Embeddable with @MappedSuperclass in one entity in JPA (EclipseLink)

切换到 EclipseLink 2.6.0(从 2.5.2)后,对于使用

声明的域 class
@MappedSuperclass
@Embeddable
public class ADomainClass { ... }

我收到一个错误:

Caused by: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [default] failed.
Internal Exception: java.lang.ClassCastException: org.eclipse.persistence.internal.jpa.metamodel.EmbeddableTypeImpl cannot be cast to org.eclipse.persistence.internal.jpa.metamodel.MappedSuperclassTypeImpl
    at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:231)
    ... 73 more
Caused by: java.lang.ClassCastException: org.eclipse.persistence.internal.jpa.metamodel.EmbeddableTypeImpl cannot be cast to org.eclipse.persistence.internal.jpa.metamodel.MappedSuperclassTypeImpl
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.preInitialize(MetamodelImpl.java:398)
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.<init>(MetamodelImpl.java:113)
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.<init>(MetamodelImpl.java:132)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.preInitializeMetamodel(EntityManagerSetupImpl.java:3755)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:2000)
    ... 71 more

在这个新版本的 EclipseLink 中,这可能是一个不需要的回归吗?

(注意我看ClassCastException的时候可以看到同一个栈帧,是我的classADomainClass造成的。)

编辑:

我的用例是 Embeddables 之间的继承。
我的超classADomainClass(也就是@Embeddable)被另一个@Embeddable扩展classASubtype不工作,除非 superclass 被注释为 @MappedSuperclass.

根据 http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#InheritanceEclipseLink / Toplink 支持此 JPA 非标准功能。虽然应该用 DescriptorCustomizerInheritancePolicy 来实现它。 (而不是 @MappedSuperclass?)

我同意@Chris 的评论,我不确定它是如何为你工作的,或者这样的目的是什么 class。 @MappedSuperclass@Embeddable 的用途完全不同。

@MappedSuperclass用于对所有实体使用的一些公共属性进行分组,如id,或一些审计信息如createdAtcreatedBy。来自 JPA 2.1 规范:

[2.11.2] Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple entity classes.

简而言之,映射的超classes将被实体扩展。实体也可以扩展非实体 classes,但在那种情况下,superclass 不会持久化,只有行为会被继承。此外,此类 class 上的所有注释都将被忽略。

[2.11.3] The non-entity superclass serves for inheritance of behavior only. The state of a non-entity superclass is not persistent. Any state inherited from non-entity superclasses is non-persistent in an inheriting entity class. This non-persistent state is not managed by the entity manager[23]. Any annotations on such superclasses are ignored.

@Embeddable用于group/embed一个实体的一些属性在一个单独的class中,也可以在其他实体中重复使用。可嵌入 class 的所有字段都映射到拥有实体中的列,除非 @ElementCollection@CollectionTable 用于存储它们。 JPA 规范没有定义可嵌入对象的继承(尽管 EclipseLink 通过使用其原生 API 支持它)EclipseLink Doc. They can also contain mappings to other entities (from JPA 2.0). Nevertheless, they are not intended to be extended by entities. From wiki

Generally attempting to mix inheritance between embeddables and entities is not a good idea, but may work in some cases.
...
Relationships to embeddable objects from entities other than the embeddable's parent are typically not a good idea, as an embeddable is a private dependent part of its parent. Generally relationships should be to the embeddable's parent, not the embeddable. Otherwise, it would normally be a good idea to make the embeddable an independent entity with its own table.