7

私の Web アプリには、それ自体と階層的な関係を持ついくつかのドメイン モデル クラスがあります。その一例は、ユーザーの投稿を分類するために使用される階層的なカテゴリ構造です。

これらのクラスの階層的な性質に関連する一般的なロジックがいくつかあります。そこで、ロジックを一般的な @MappedSuperclass アノテーション付きスーパークラスに移動しようとしました。

何かのようなもの :

@MappedSuperclass
public abstract class HierarchicalBaseEntity<N extends HierarchicalBaseEntity<N>>
        extends BaseEntity {

    @ManyToOne(optional=true)
    @JoinColumn(name="parent")
    private N parent;

    private int depth;

    public N getParent() { ...
    public void setParent(N newParent) { ...

    public boolean isRoot() { ...
    public int getDepth() { ...

    public boolean isDescendantOf(N ancestor) { ...
    public static <N extends HierarchicalBaseEntity<N>> N getCommonAncestor(N a, N b) { ...
    public static <N extends HierarchicalBaseEntity<N>> Collection<N> reduceToCommonAncestors(Collection<N> entities) { ...
}

次にサブクラスは HierarchicalBaseEntity を拡張し、自身をジェネリック型 N として提供します。

@Entity
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> {

Java では、これはすべて非常にきれいに機能します。しかし残念ながら、EclipseLink は一般的な「親」フィールドを好まないようです。

private N parent;

次の例外が発生します。

Caused by: Exception [EclipseLink-7250] (Eclipse Persistence Services - 2.1.0.v20100614-r7608): org.eclipse.persistence.exceptions.ValidationException
Exception Description: [class net.timp.yaase.core.model.HierarchicalBaseEntity] uses a non-entity [class java.lang.String] as target entity in the relationship attribute [field parent].
at org.eclipse.persistence.exceptions.ValidationException.nonEntityTargetInRelationship(ValidationException.java:1341)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor.getReferenceDescriptor(RelationshipAccessor.java:416)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:609)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:678)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:107)

非エンティティ文字列について不平を言うのはなぜですか?

テストとして、ジェネリックを削除して、親フィールドを次のように定義してみました。

private HierarchicalBaseEntity parent;

ジェネリックがない場合、EclipseLink は次の例外を与えました。

Caused by: Exception [EclipseLink-7250] (Eclipse Persistence Services - 2.1.0.v20100614-r7608): org.eclipse.persistence.exceptions.ValidationException
Exception Description: [class net.timp.yaase.core.model.OnymBean] uses a non-entity [class net.timp.yaase.core.model.HierarchicalBaseEntity] as target entity in the relationship attribute [field parent].
at org.eclipse.persistence.exceptions.ValidationException.nonEntityTargetInRelationship(ValidationException.java:1341)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor.getReferenceDescriptor(RelationshipAccessor.java:416)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:609)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:678)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:107)

True HierarchicalBaseEntity どちらの場合もエンティティではなく、@MappedSuperclass .. ですが、ジェネリックなどでこれを行う方法はありますか? サブクラスの 1 つを参照する @MappedSuperclass にフィールドを持つことはできないようです。

4

3 に答える 3

5

問題は、リレーションシップのフィールド タイプとして Generics を使用する場合、実際のインスタンスが検査される実行時まで、EclipseLink がターゲット タイプを認識できないことです。そのため、マッピングは実行時に動的に作成する必要があり、これはサポートされていません。

Generic SuperClass を引き続き使用することもできますが、これには、型が定義されているエンティティにフィールドを移動する必要があり、その後、ジェネリック メソッドがジェネリック型へのキャストを呼び出す Object を返すフィールドの抽象内部ゲッター/セッターが必要になります。複雑ですが、Generic MappedSuperclass を許可します。

于 2010-08-09T13:14:26.860 に答える
1

私は遅れていると思いますが、この問題に対する答えを探している人 (私のように) は、これを見てください: https://bugs.eclipse.org/bugs/show_bug.cgi?id=312132

于 2010-09-17T17:12:21.450 に答える