У меня проблема при попытке отобразить дерево наследования. Упрощенная версия моей модели выглядит так:
@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 такой, какая она есть?
Любая помощь будет принята с благодарностью.