使用JPA(+Hibernate)继承抽象类

55

在下面的示例代码中,你如何配置注解?我想坚持使用JPA注解并避免使用Hibernate特定的依赖项。下面的代码是否正确?

@Entity
public class RefExample extends RefData {

}

这些类将有多个版本,例如RefSomeOtherExample等,并且每个类都对应一张数据库表。某些类可能会添加额外的字段(列),但大多数类只是利用从“RefData”基类继承的基本字段。

基类:

@Entity
public abstract class RefData {

    private long id;
    private String code;
    private String desc;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true, nullable = false)
    public long getId() {

        return id;
    }

    public void setId(long id) {

        this.id = id;
    }

    @Column(unique = true, nullable = false, length=8)
    public String getCode() {

        return code;
    }

    public void setCode(String code) {

        this.code = code;
    }

    @Column(unique = true, nullable = false, length=80)
    public String getDesc() {

        return desc;
    }

    public void setDesc(String desc) {

        this.desc = desc;
    }
}

最终我希望使用Hibernate的SchemaExport类从此生成模式创建脚本。在上述情况下,这两个类应该只会创建一个名为"RefExample"的表格,并包含来自"RefData"的三列。这样会有效吗?

3个回答

114

根据JPA 1.0规范:

抽象类和具体类都可以成为实体。 抽象类和具体类都可以注释@Entity,并将其映射为实体,也可以作为实体进行查询

实体可以扩展非实体类,非实体类也可以扩展实体类

如果想要一个单一的表,您应该使用单表继承

只需定义一个鉴别器列如下:

@Entity
@DiscriminatorColumn(name="REF_TYPE")
public abstract class RefData {

但是如果您不想依赖于JPA的继承策略,可以使用MappedSuperclass:

@MappedSuperclass
public abstract class RefData {

JPA规范

实体可以继承自提供持久化实体状态和映射信息但本身并非实体的超类。通常,这样一个映射的超类的目的是定义多个实体类共用的状态和映射信息

请注意,您不能同时使用@Entity和@MappedSuperclass注释。


@Crusader 请看这里:https://dev59.com/xU3Sa4cB1Zd3GeqPul-B#3017146 我是如何解决继承时的性能问题的。如果你想使用TABLE PER CLASS策略,目标数据库必须支持identity生成策略 - Arthur Ronald
1
我还不确定,但我认为MappedSuperclass可能是最好的选择。所有这些表格真正需要做的就是存储在下拉字段中呈现的值,这些值被分配(一对多)给实际数据记录。 - Manius
在使用@MappedSuperclass注解标记的超类中,是否可以查询(HQL或JPQL)存在的属性? - Sunil

7

@MappedSuperclass对我很有用。我一直在努力将一个视图映射到两个对象,即父类和子类。我的视图是从两个表中连接而成的。这两个表的主键都存在于视图中。 @DiscriminatorColumn 对我没有用,因为它需要一个专门分配给对象数据类型的列,并且它会抛出“对象异常中重复列”的错误,我无法解决。

我阅读了这个论坛,尝试了@MappedSuperclass注释。它起到了作用。

我在超类中放置了@MappedSuperclass,并在超类标识符中放置了@Id@GeneratedValue。在子类中,我给出了:

@Entity
@Table(name="view_name")

我使用子类对象从视图中获取数据。就是这样。

Hibernate注解中的继承对于不使用@DiscriminatorColumn的联合表很有效。


0

您可以使用继承策略之一来实现此目的。您的情况似乎是层次结构的单个类的情况。

请查看this


1
那篇文章让我感到困惑。我实际上正在构思其中描述的每个具体类策略(每个具体“RefExample”类一个表),但它说这种方法在JPA中“不流行”且是可选的。三个选项似乎都不能完全满足我的要求。糟糕! - Manius
这篇文章中的链接似乎已经失效了。 - Stephan

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