Problem persisting inheritance tree

Posted by alaiseca on Stack Overflow See other posts from Stack Overflow or by alaiseca
Published on 2010-05-11T18:16:28Z Indexed on 2010/05/11 18:24 UTC
Read the original article Hit count: 188

Filed under:
|
|
|

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.

© Stack Overflow or respective owner

Related posts about hibernate

Related posts about inheritance