代码之家  ›  专栏  ›  技术社区  ›  Tauren

抽象超类的Hibernate(JPA)继承映射

  •  29
  • Tauren  · 技术社区  · 14 年前

    我的数据模型代表法律实体,如企业或个人。两者都是纳税实体,都有计税表、电话号码和邮寄地址。

    我有一个Java模型,它有两个扩展抽象类的具体类。抽象类具有两个具体类共有的属性和集合。

    AbstractLegalEntity        ConcreteBusinessEntity    ConcretePersonEntity
    -------------------        ----------------------    --------------------
    Set<Phone> phones          String name               String first
    Set<Address> addresses     BusinessType type         String last
    String taxId                                         String middle
    
    Address                    Phone
    -------                    -----
    AbsractLegalEntity owner   AbstractLegalEntity owner
    String street1             String number
    String street2           
    String city
    String state
    String zip
    

    我在用 冬眠 JPA注释 在一个 MySQL数据库 数据库,类如下:

    @MappedSuperclass
    public abstract class AbstractLegalEntity {
        private Long id;  // Getter annotated with @Id @Generated
        private Set<Phone> phones = new HashSet<Phone>();  // @OneToMany
        private Set<Address> address = new HashSet<Address>();  // @OneToMany
        private String taxId;
    }
    
    @Entity
    public class ConcretePersonEntity extends AbstractLegalEntity {
        private String first;
        private String last;
        private String middle;
    }
    
    @Entity
    public class Phone {
        private AbstractLegalEntity owner; // Getter annotated @ManyToOne @JoinColumn
        private Long id;
        private String number;
    }
    

    问题是 Phone Address 对象需要引用其所有者,这是 AbstractLegalEntity . Hibernate抱怨道:

    @OneToOne or @ManyToOne on Phone references an unknown 
    entity: AbstractLegalEntity
    

    看起来这是一个相当常见的Java继承场景,所以我希望Hibernate能够支持它。我试着根据 Hibernate forum question ,不再使用 @MappedSuperclass :

    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    

    但是,现在我得到以下错误。在阅读这个继承映射类型时,看起来我必须使用SEQUENCE而不是IDENTITY,而且MySQL不支持SEQUENCE。

    Cannot use identity column key generation with <union-subclass> 
    mapping for: ConcreteBusinessEntity
    

    当我使用下面的映射时,我在工作方面取得了更大的进展。

    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(
            name="entitytype",
            discriminatorType=DiscriminatorType.STRING
    )
    

    我想我应该继续走这条路。我担心的是我把它映射成 @Entity 当我真的不希望抽象实体合法存在的时候。我想知道这是不是正确的方法。对于这种情况,我应该采取什么样的正确方法?

    3 回复  |  直到 14 年前
        1
  •  42
  •   milbr    14 年前

    使用:

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    AbstractLegalEntity
    

    然后在数据库中,您将有一个表用于AbstractLegalEntity,还有一个表用于扩展AbstractLegalEntity类的类。如果是抽象的,就不会有抽象法律的实例。多态性可以在这里使用。

    使用时:

    @MappedSuperclass
    AbstractLegalEntity
    
    @Entity
    ConcretePersonEntity extends AbstractLegalEntity
    

    它在数据库中只创建一个表ConcretePersonEntity,但使用两个类中的列。

        2
  •  1
  •   andbi    14 年前

    添加 @Entity 注释到 AbstractLegalEntity . 实例 抽象法学 永远不会存在——Hibernate将加载适当的扩展实例 ConcreteBusinessEntity ConcretePersonEntity 根据Id字段。

        3
  •  1
  •   Nicolas    14 年前

    你必须申报 AbstracLegalEntity 作为 @Entity . 即使有 @实体 注释,您的类仍然是抽象的。因此,您将只拥有具体子类的实例。

    推荐文章