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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4265454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:10:13  来源:igfitidea点击:

Hibernate (JPA) inheritance mapping of abstract super classes

javahibernatejpa

提问by Tauren

My data model represents legal entities, such as a Business or a Person. Both are tax-paying entities, and both have a TaxID, a collection of phone numbers, and a collection of mailing addresses.

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

I have a Java model with two concrete classes that extend an abstract class. The abstract class has properties and collections that are common to both concrete classes.

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

I'm using HibernateJPA Annotationson a MySQLdatabase, with classes like this:

我在MySQL数据库上使用HibernateJPA Annotations,类如下:

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

The problem is that Phoneand Addressobjects need to refer to their owner, which is an AbstractLegalEntity. Hibernate complains:

问题是PhoneandAddress对象需要引用它们的所有者,这是一个AbstractLegalEntity. 休眠抱怨:

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

It seems like this would be a fairly common Java inheritance scenario, so I hope that Hibernate would support it. I've tried changing the mapping for AbstractLegalEntity based on a Hibernate forum question, no longer using @MappedSuperclass:

看起来这将是一个相当常见的 Java 继承场景,所以我希望 Hibernate 支持它。我已经尝试根据Hibernate 论坛问题更改 AbstractLegalEntity 的映射,不再使用@MappedSuperclass

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

However, now I get the following error. When reading up on this inheritance mapping type, it looks like I have to use SEQUENCE not IDENTITY, and MySQL doesn't support SEQUENCE.

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

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

I'm making more progress toward getting things working when I use the following mapping.

当我使用以下映射时,我在使事情正常工作方面取得了更多进展。

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

I'm thinking I should continue down this path. My concern is that I'm mapping it as an @Entitywhen I really don't ever want an instance of AbstractLegalEntity to ever exist. I'd like to know if this is the right approach. What is the correct approach I should be taking for this situation?

我想我应该继续沿着这条路走下去。我担心的是,@Entity当我真的不希望 AbstractLegalEntity 的实例存在时,我将其映射为一个。我想知道这是否是正确的方法。对于这种情况,我应该采取什么正确的方法?

采纳答案by milbr

Use:

用:

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

Then in database you will have one table for AbstractLegalEntity and tables for classes which extends AbstractLegalEntity class. You won't have instances of AbstractLegalEntity if it's abstract. Polymorphism can be here used.

然后在数据库中,您将有一个 AbstractLegalEntity 表和扩展 AbstractLegalEntity 类的类表。如果它是抽象的,您将没有 AbstractLegalEntity 的实例。这里可以使用多态。

When you use:

当您使用:

@MappedSuperclass
AbstractLegalEntity

@Entity
ConcretePersonEntity extends AbstractLegalEntity

It creates in database just one table ConcretePersonEntity but with columns from both classes.

它在数据库中只创建一个表 ConcretePersonEntity 但包含来自两个类的列。

回答by andbi

Add @Entityannotation to AbstractLegalEntity. Instance of AbstractLegalEntitywill never exist - hibernate will load appropriate extending instances - ConcreteBusinessEntityor ConcretePersonEntityaccording to Id field.

添加@Entity注释到AbstractLegalEntity. 实例AbstractLegalEntity永远不会存在——休眠将加载适当的扩展实例——ConcreteBusinessEntity或者ConcretePersonEntity根据 Id 字段。

回答by Nicolas

You have to declare AbstracLegalEntityas an @Entity. Even with the @Entityannotation, your class remains abstract. consequently, you will only have instance of concrete subclasses.

您必须声明AbstracLegalEntity@Entity. 即使有@Entity注释,您的类仍然是抽象的。因此,您将只有具体子类的实例。