JPA/Hibernate - InheritanceType.JOINED 的行为类似于 InheritanceType.TABLE_PER_CLASS

发布于 2024-11-07 20:40:14 字数 1947 浏览 0 评论 0原文

我正在尝试在 Hibernate 中实现一个非常简单的继承模型。基本上我有一个可以称为 A 的超类,以及几个继承自 A 的子类。由于我看到的行为对于所有这些都是相同的,因此可以将它们称为 B

我想要达到的是所描述的 此处,第 6.2 节。基本上,应该有一个包含其字段的 A 表,以及一个仅包含与子类不同的字段的 B 表,以及一个连接列到 A 的表。我正在使用 Hibernate 的自动模式生成(仅针对开发持久性单元启用)。

然而,当我查看架构时,我看到的是 A 的表,其中包含其字段(正确),以及 B 的表,其中包含以下所有字段A(不正确),加上 B 中添加的字段。我的课程注释如下:

@Entity
@Table(name="A")
@Inheritance(strategy = InheritanceType.JOINED)
public class A implements Serializable {
    protected long id;
    protected Date createDate;
    protected String title;
    protected boolean hidden;

    public A() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreateDate() {
        return createDate;
    }

    @Column(nullable = false)
    public boolean isHidden() {
        return hidden;
    }

    @Column(nullable = false)
    public String getTitle() {
        return title;
    }

    //also setters...   
}

@Entity
@Table(name="B")
@PrimaryKeyJoinColumn(name="aId", referencedColumnName="id")
public class B extends A {
    private String extraField;

    public B() {
        super();
    }

    @Column
    public String getExtraField() {
        return extraField;
    }

    //also setter...
}

你知道我做错了什么吗?具体来说,当我查看生成的数据库模式时,我想看到的是这样的:

Table A:  {id, createDate, title, hidden}
Table B:  {aId, extraField}

...而我得到的是:

Table A:  {id, createDate, title, hidden}
Table B:  {id, createDate, title, hidden, extraField}

使用 Hibernate 的自动模式生成是不可能的,还是我在某处搞砸了注释?

I'm trying to implement a very simple inheritance model in Hibernate. Basically I have a single superclass which can be called A, and several subclasses all of which inherit from A. Since the behavior I'm seeing is the same for all of them, they can just be referred to as B.

What I'm trying to arrive at is what's described here in section 6.2. Basically, there should be a table for A that contains its fields, and a table for B that contains only the fields that are distinct to the subclass, plus a join column back to the table for A. I am using Hibernate's automatic schema generation (enabled for the development persistence-unit only).

What I see when I look at the schema, however, is a table for A the contains its fields (correct), and a table for B which contains all the fields in A (incorrect), plus the fields added in B. My classes are annotated as follows:

@Entity
@Table(name="A")
@Inheritance(strategy = InheritanceType.JOINED)
public class A implements Serializable {
    protected long id;
    protected Date createDate;
    protected String title;
    protected boolean hidden;

    public A() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreateDate() {
        return createDate;
    }

    @Column(nullable = false)
    public boolean isHidden() {
        return hidden;
    }

    @Column(nullable = false)
    public String getTitle() {
        return title;
    }

    //also setters...   
}

@Entity
@Table(name="B")
@PrimaryKeyJoinColumn(name="aId", referencedColumnName="id")
public class B extends A {
    private String extraField;

    public B() {
        super();
    }

    @Column
    public String getExtraField() {
        return extraField;
    }

    //also setter...
}

Any ideas what I've done wrong? Specifically, what I want to see when I look at the generated DB schema is something like:

Table A:  {id, createDate, title, hidden}
Table B:  {aId, extraField}

...and instead what I get is:

Table A:  {id, createDate, title, hidden}
Table B:  {id, createDate, title, hidden, extraField}

Is this just not possible using Hibernate's automatic schema generation, or have I screwed up the annotations somewhere?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温暖的光 2024-11-14 20:40:14

您的注释是正确的,它应该生成您想要的表模式。

但现在您得到了一个不需要的 schema ,它正是使用每个具体类一个表策略(即@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS))生成的模式。因此,我认为可能的原因之一是配置中的 hibernate.hbm2ddl.auto 属性使用默认值,即 update 。

update 值的行为是:

  • Hibernate 将尝试创建一个
    更新脚本以更新数据库
    架构到当前映射时
    SessionFactory 已创建。

  • 如果更新语句不能
    执行 ,它将被跳过(对于
    向 a 添加非空列的示例
    表与现有数据)

  • Hibernate 不会删除任何数据
    更新期间。(例如,如果
    列的名称改变了,只是
    添加具有新名称的新列,
    但仍保留该列
    原名)

所以,我认为你必须使用@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)来生成之前的模式,从而产生了以下模式。表 A 和表 B 彼此之间没有任何外键关联。

Table A:  {id, createDate, title, hidden}
Table B:  {id, createDate, title, hidden, extraField}

之后,您更改为使用 @Inheritance(strategy = InheritanceType.JOINED) 。在更新模式过程中,hibernate 只是通过在 TableA.idTableB.id 之间添加外键关联来更新您的模式。它将所有其他列保留在表 B 中。这就是为什么即使您的注释是正确的,您也会获得当前架构。

在启动 hibernate 程序之前从数据库中删除表 A 和表 B 后,应生成所需的表模式。或者,您可以将hibernate.hbm2ddl.auto设置为create,然后hibernate将在生成表模式之前删除所有表。

Your annotation is correct , it should produce the table schema that you want .

But now you get an undesired schema , which is exactly the schema produced using the Table per concrete class strategy (i.e @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)). So , I think one of the possible reason is that the hibernate.hbm2ddl.auto property in your configuration uses the default value , which is update .

The behavior of the update value is :

  • Hibernate will try to create an
    update script to update the database
    schema to the current mapping when
    the SessionFactory is created.

  • If an update statement cannot be
    performed , it will be skipped (For
    example adding a not null column to a
    table with existing data)

  • Hibernate will not delete any data
    during the update .(For example , if
    a column 's name is changed , it just
    add an new column with the new name ,
    but still keep the column with the
    original name)

So , I think you must use @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) to generate the schema before , which produced the following schema . Table A and Table B do not have any foreign key associations to each other.

Table A:  {id, createDate, title, hidden}
Table B:  {id, createDate, title, hidden, extraField}

After that , you changed to use @Inheritance(strategy = InheritanceType.JOINED) . During the update schema process , hibernate just updated your scheme by adding a foreign key assocation between the TableA.id and TableB.id . It kept all other columns in Table B . That 's why you get the current schema even though your annotation is correct .

The desired table schema should be generated after you drop Table A and Table B from the DB before starting the hibernate programe . Alternatively , you can set the hibernate.hbm2ddl.auto to create , then hibernate will delete all tables before generating the table schema .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文