Проблема сохранения дерева наследования - PullRequest
0 голосов
/ 11 мая 2010

У меня проблема при попытке отобразить дерево наследования. Упрощенная версия моей модели выглядит так:

@MappedSuperclass
@Embeddable
public class BaseEmbedded implements Serializable {

   @Column(name="BE_FIELD")
   private String beField;

   // Getters and setters follow
}

@MappedSuperclass
@Embeddable
public class DerivedEmbedded extends BaseEmbedded {

  @Column(name="DE_FIELD")
   private String deField;

   // Getters and setters follow
}

@MappedSuperclass
public abstract class BaseClass implements Serializable {

   @Embedded
   protected BaseEmbedded embedded;

    public BaseClass() {
      this.embedded = new BaseEmbedded();
    }

     // Getters and setters follow    
}

@Entity
@Table(name="MYTABLE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
public class DerivedClass extends BaseClass {

    @Id
    @Column(name="ID", nullable=false)
    private Long id;

    @Column(name="TYPE", nullable=false, insertable=false, updatable=false)
    private String type;

    public DerivedClass() {
        this.embedded = new DerivedClass();
    }

    // Getters and setters follow
}

@Entity
@DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {

    @Embeddable
    public static NestedClassA extends DerivedEmbedded {

            @Column(name="FIELD_CLASS_A")
            private String fieldClassA;
    }

    public DerivedClassA() {
        this.embedded = new NestedClassA();
    }

    // Getters and setters follow
}

@Entity
@DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {

    @Embeddable
    public static NestedClassB extends DerivedEmbedded {

            @Column(name="FIELD_CLASS_B")
            private String fieldClassB;
    }

    public DerivedClassB() {
        this.embedded = new NestedClassB();
    }

    // Getters and setters follow
}

На уровне Java эта модель работает нормально, и я считаю, что она подходит. Моя проблема возникает, когда пришло время сохранить объект.

Во время выполнения я могу создать объект, который может быть экземпляром DerivedClass, DerivedClassA или DerivedClassB. Как видите, каждый из производных классов представляет новое поле, которое имеет смысл только для этого конкретного производного класса. Все классы используют одну и ту же физическую таблицу в базе данных. Если я сохраню объект типа DerivedClass, я ожидаю, что поля BE_FIELD, DE_FIELD, ID и TYPE будут сохранены со своими значениями, а остальные поля будут нулевыми. Если я сохраню объект типа DerivedClass A, я ожидаю, что те же поля плюс поле FIELD_CLASS_A будут сохранены с их значениями, а поле FIELD_CLASS_B будет нулевым. Нечто эквивалентное для объекта типа DerivedClassB.

Поскольку аннотация @Embedded присутствует только в базовом классе, Hibernate сохраняет поля только до этого уровня в дереве. Я не знаю, как сказать Hibernate, что я хочу сохранить до соответствующего уровня в дереве, в зависимости от фактического типа встроенного свойства.

У меня не может быть другого свойства @Embedded в подклассах, поскольку это будет дублировать данные, которые уже присутствуют в суперклассе, и также нарушит модель Java.

Я также не могу объявить встроенное свойство более определенного типа, поскольку только во время выполнения создается реальный объект, и у меня нет ни одной ветви в иерархии.

Возможно ли решить мою проблему? Или я должен смириться с тем, чтобы признать, что нет способа сохранить модель Java такой, какая она есть?

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 03 июня 2010

Ничего себе. Это упрощенная версия? Я предполагаю, что поведение, которое вы видите, состоит в том, что поле BaseEmbedded сохраняется, но не FIELD_CLASS_A или B?

Проблема в том, что когда Hibernate отображает классы DerivedClassA и B, он отражает и видит встроенное поле как класс BaseEmbedded. Просто потому, что вы затем сохраняете объект со встроенным полем, являющимся NestedClass, отображение уже выполнено, и на FIELD_CLASS_A и B никогда не ссылаются.

Что вам нужно сделать, это избавиться от NestedClass * и встроенного поля, и вместо этого, чтобы fieldClassA и B были обычными членами DerivedClassA и B. Затем добавьте поле name к @Entity, которое будет они оба в одной таблице, я верю. Это позволит вам еще больше свернуть / упростить иерархию классов.

См .: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1168

@Entity(name = "DerivedClass")
@DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {

    @Column(name="FIELD_CLASS_A")
    private String fieldClassA;

...

@Entity(name = "DerivedClass")
@DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {

    @Column(name="FIELD_CLASS_B")
    private String fieldClassB;

...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...