2010-05-11 5 views
0

J'ai un problème pour essayer de mapper un arbre d'héritage. Une version simplifiée de mon modèle est comme ceci:Problème de l'arbre d'héritage persistant

@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 
} 

Au niveau Java, ce modèle fonctionne bien, et je crois est celui qui convient. Mon problème arrive quand il est temps de persister un objet. Au moment de l'exécution, je peux créer un objet qui pourrait être une instance de DerivedClass, DerivedClassA ou DerivedClassB. Comme vous pouvez le voir, chacune des classes dérivées introduit un nouveau champ qui n'a de sens que pour cette classe dérivée spécifique. Toutes les classes partagent la même table physique dans la base de données. Si je persiste un objet de type DerivedClass, j'attends que les champs BE_FIELD, DE_FIELD, ID et TYPE soient conservés avec leurs valeurs et que les champs restants soient NULL. Si je persiste un objet de type DerivedClass A, je m'attends à ce que ces mêmes champs et le champ FIELD_CLASS_A soient conservés avec leurs valeurs et que le champ FIELD_CLASS_B soit nul. Quelque chose d'équivalent pour un objet de type DerivedClassB.

Étant donné que l'annotation @Embedded se trouve uniquement dans BaseClass, Hibernate ne conserve les champs que jusqu'à ce niveau dans l'arborescence. Je ne sais pas comment dire à Hibernate que je veux persister jusqu'au niveau approprié dans l'arbre, en fonction du type réel de la propriété incorporée.

Je ne peux pas avoir une autre propriété @Embedded dans les sous-classes car cela dupliquerait les données déjà présentes dans la superclasse et briserait également le modèle Java.

Je ne peux pas non plus déclarer que la propriété incorporée est d'un type plus spécifique, puisque c'est seulement à l'exécution quand l'objet réel est créé et que je n'ai pas une seule branche dans la hiérarchie.

Est-il possible de résoudre mon problème? Ou devrais-je me résigner à accepter qu'il n'y a aucun moyen de maintenir le modèle Java tel quel?

Toute aide sera grandement appréciée.

+0

aide par mes réponse à tout? – Gray

Répondre

0

Wow. C'est la version simplifiée? Je suppose que le comportement que vous voyez est que le champ BaseEmbedded est persistant mais pas le FIELD_CLASS_A ou B? Le problème est que lorsque Hibernate mappe les classes DerivedClassA et B, il reflète et voit le champ incorporé en tant que classe BaseEmbedded. Juste parce que vous persistez alors un objet avec le champ incorporé étant une NestedClass, le mappage a déjà été fait et les FIELD_CLASS_A et B ne sont jamais référencés.

Ce que vous devez faire est de se débarrasser de la NestedClass * et sur le terrain intégré et ont plutôt le fieldClassA et B membres normaux de DerivedClassA et B. Puis ajouter ajouter un champ name à la @Entity qui les mettra à la fois dans la même table je crois. Cela vous permettra de réduire/simplifier votre hiérarchie de classe beaucoup plus loin.

Voir: 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; 

... 
Questions connexes