EclipseLink @MappedSuperclass и дженерики - PullRequest
6 голосов
/ 08 августа 2010

В моем веб-приложении есть несколько классов модели предметной области, которые имеют иерархическое отношение к себе.Примером этого является иерархическая структура категорий, используемая для классификации сообщений пользователей.

Существует некоторая логика, относящаяся к иерархической природе этих классов, которая является общей.Поэтому я попытался переместить логику в универсальный аннотированный суперкласс @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 ... но есть ли способ сделать это с помощью обобщений или иным образом?Кажется, в вашем @MappedSuperclass не может быть поля, которое ссылается на один из его подклассов.

Ответы [ 3 ]

4 голосов
/ 09 августа 2010

Проблема в том, что при использовании Generics в качестве типов полей для отношений EclipseLink не может знать, что является целевым типом, до времени выполнения, когда проверяется фактический экземпляр.Таким образом, отображение должно создаваться динамически во время выполнения, и это не поддерживается.

Вы можете продолжать использовать универсальный суперкласс, но для этого потребуется переместить поле в сущности, в которых они будут иметь определенные типы, а затем иметь абстрактныйвнутренние методы получения / установки для тех полей, которые возвращают объект, который универсальные методы будут вызывать приведение к универсальному типу.Свернуто, но это позволило бы универсальный MappedSuperclass.

1 голос
/ 17 сентября 2010

Я думаю, что опоздал, но люди, ищущие ответ на эту проблему (как я), должны взглянуть на это: https://bugs.eclipse.org/bugs/show_bug.cgi?id=312132

0 голосов
/ 13 марта 2015

Другим поставщиком, который поддерживает универсальный тип в постоянном отношении, является OpenJPA . Предположение OpenJPA состоит в том, что поле универсального типа является постоянным типом и должно быть помечено как таковое аннотацией @Type (специфичной для OpenJPA).

Эта аннотация @Type действует как заполнитель для механизма отображения OpenJPA и содержит отображение, где ссылка - это постоянная идентификация экземпляра среды выполнения. Много лет назад я написал блог ; Я цитирую это здесь снова не для саморекламы, но надеюсь, что это может указывать на некоторые пути для поддержки универсального дерева без необходимости опускать конкретную информацию о типе вниз по иерархии типов (и, таким образом, терять сущность модели типов на основе универсального типа). ).

...