2010-05-11 77 views
0

尝试映射继承树时出现问题。我的模型的简化版本是这样的:问题持续存在继承树

@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注释仅在BaseClass中,因此Hibernate仅在树中保留高达该级别的字段。我不知道如何告诉Hibernate,我想根据嵌入式属性的实际类型将其持久保存到树中的适当级别。

我不能在子类中拥有另一个@Embedded属性,因为这会重复已经存在于超类中的数据并且还会中断Java模型。

我不能声明嵌入属性是一个更具体的类型,因为它只是在运行时创建实际的对象,而我没有在层次结构中的单个分支。

有没有可能解决我的问题?还是应该让我自己接受,认为没有办法坚持Java模型,因为它是?

任何帮助将不胜感激。

+0

难道我的回答帮助呢? – Gray 2010-07-20 01:31:22

回答

0

哇。这是简体版版本?我假设你看到的行为是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; 

...