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

32

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

我有一个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

我正在使用Hibernate 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;
}

问题在于PhoneAddress对象需要引用它们的所有者,也就是一个AbstractLegalEntity。Hibernate会报错:
@OneToOne or @ManyToOne on Phone references an unknown 
entity: AbstractLegalEntity

看起来这应该是一个相当普遍的Java继承场景,所以我希望Hibernate能够支持它。我已经尝试根据Hibernate论坛问题更改了AbstractLegalEntity的映射,不再使用@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,但我真的不希望 AbstractLegalEntity 的任何实例存在。我想知道这是否是正确的方法。在这种情况下,我应该采取什么正确的方法呢?


1
你正在使用Hibernate中的JPA注释,而不是Hibernate注释。这是一个重要的区别。 - Sean Patrick Floyd
@S.P.Floyd - 啊,没错。感谢你在我的问题中指出了错误。 - Tauren
3个回答

46

使用:

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

在数据库中,您将有一个表用于AbstractLegalEntity,以及继承AbstractLegalEntity类的类的表。如果AbstractLegalEntity是抽象的,则不会有AbstractLegalEntity的实例。可以在这里使用多态性。

当您使用:

    @MappedSuperclass
    AbstractLegalEntity
    
    @Entity
    ConcretePersonEntity extends AbstractLegalEntity

这将在你的数据库中创建一个名为ConcretePersonEntity的表,其中包含来自两个类的列。


谢谢,这有助于澄清事情。我也能够使用SINGLE_TABLE,当我想要更少的连接并且类层次结构中没有大量字段时,这是有意义的。 - Tauren
+1 我也有类似的问题。你能帮我解决吗?特别是,我需要关于DDL和实体定义的帮助。我已经发布了我的代码。这是链接:https://dev59.com/doLba4cB1Zd3GeqPd2N2 - CodeMed

1
@Entity 注释添加到 AbstractLegalEntity AbstractLegalEntity 的实例将永远不存在 - hibernate将加载适当的扩展实例 - 根据Id字段加载 ConcreteBusinessEntity ConcretePersonEntity

9
一个类不能同时被标记为 @Entity@MappedSuperClass ! - Stephan

1
你需要将AbstracLegalEntity声明为一个@Entity。即使有了@Entity注解,你的类仍然是抽象的。因此,你只能有具体子类的实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接