I have a problem trying to map an inheritance tree. A simplified version of my model is like this:
@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
}
At Java level, this model is working fine, and I believe is the appropriate one. My problem comes up when it's time to persist an object.
At runtime, I can create an object which could be an instance of DerivedClass, DerivedClassA or DerivedClassB. As you can see, each one of the derived classes introduces a new field which only makes sense for that specific derived class. All the classes share the same physical table in the database. If I persist an object of type DerivedClass, I expect fields BE_FIELD, DE_FIELD, ID and TYPE to be persisted with their values and the remaining fields to be null. If I persist an object of type DerivedClass A, I expect those same fields plus the FIELD_CLASS_A field to be persisted with their values and field FIELD_CLASS_B to be null. Something equivalent for an object of type DerivedClassB.
Since the @Embedded annotation is at the BaseClass only, Hibernate is only persisting the fields up to that level in the tree. I don't know how to tell Hibernate that I want to persist up to the appropriate level in the tree, depending on the actual type of the embedded property.
I cannot have another @Embedded property in the subclasses since this would duplicate data that is already present in the superclass and would also break the Java model.
I cannot declare the embedded property to be of a more specific type either, since it's only at runtime when the actual object is created and I don't have a single branch in the hierarchy.
Is it possible to solve my problem? Or should I resignate myself to accept that there is no way to persist the Java model as it is?
Any help will be greatly appreciated.