【问题标题】:Inheritance with Java and Hibernate - Typecasting on updatesJava 和 Hibernate 的继承 - 更新时的类型转换
【发布时间】:2019-03-29 15:23:55
【问题描述】:

我的类中有以下层次结构

@Entity
@Table(name = "Parent")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Parent {
}

@Entity
@DiscriminatorVlaue("FirstChild")
public class FirstChild extends Parent {
}

@Entity
@DiscriminatorVlaue("SecondChild")
public class SecondChild extends Parent {
}

这会按预期创建一个表 Parent。

我的应用中的一些业务逻辑:

当请求被接受时,它被持久化为“父”类型并在表中创建以下条目

Dtype    id  value
Parent   1   "some value"

在处理请求时,它可以是 FirstChild 类型或 SecondChild 类型,所以在我的代码中我有

if (some condition is met) {
// change the Parent to its firstChild type
}
else {
// chnage it to "SecondChild" type
}

我对继承的理解和使用正确吗?我本质上是在抛出运行时异常的 if 循环中向下转换对象,但是更改对象的类型是否也会更改数据库中的 DTYPE 值?我本质上是使用继承来将事物组织为它们的类型。我可以在构造函数中做一些魔术来实现这一点吗?但真正的问题是 Dtype 在更新时可以修改吗?

为了进一步解决这个问题,

我在子类中创建了构造函数

public FirstChild(Parent parent) {
id = parent.id
}

但这会为子类型创建一个新行,

  Dtype       id  value
  Parent      1   "some value"
  FirstChild  2   "some value"

我正在确保使用父 ID (1) 创建“firstChild”记录,但我不确定为什么要创建第二行

【问题讨论】:

  • 对不起,这是一个复制粘贴错误,我确实有 DiscriminatorColumn,我只是想更改更新的类型
  • 你不能,就像你不能改变Java中对象的类型一样。您可能应该使用 has-a 关联而不是 is-a。
  • 那么用hibernate继承有什么价值呢?它在 Java 对象中非常有意义
  • // change the Parent to its firstChild type是什么意思?你的代码是什么样子的?

标签: java hibernate inheritance constructor


【解决方案1】:

关系数据库中没有真正的继承。 Hibernate 只是模拟它。继承是一个编程概念,可以使用其他类,如所有者。但是你不能使用其他表作为拥有表。在子表中,如果你有一个元素而不是你有一个父元素,但父元素在哪里? Parent也是一个元素..(一行数据)。所以你在数据库中模拟它。 Hibernate有一些继承策略。'SINGLE_TABLE'就是其中之一,将父表和子表收集在一张表中。区分哪个类型是哪个类在数据库上使用“DiscriminatorColumn”。此列无法更改,它是静态的并使用您的 java 类声明。您可以使用“DiscriminatorValue”选择一个值来标识“DiscriminatorColumn”处的 Java 类。 所以你对继承的理解在关系数据库上是不同的。您必须在父表行上声明每个子行数据...

【讨论】:

    【解决方案2】:

    但真正的问题是 Dtype 是否可以在更新时修改?

    不,你不能:source

    从您的示例中,您的纯 java 代码将如下所示:

    Parent parent = new Parent(); //object received from request, stored in database as it is
    if (some conditions is met) {
       // FirstChild firstChild = (Parent) parent; //this would throw ClassCastException
       FirstChild firstChild = new FirstChild(parent); //creating new object, gc will collect parent
    }
    

    所以hibernate的行为与java相同:你不能更新Parent,你必须为firstChild创建新记录并删除parent

    在处理请求时使用@DiscriminatorFormula 而不是检查some condition is met 对您没有帮助吗?

    @DiscriminatorFormula("case when value = 'some value' then 'FirstChild' else 'SecondChild' end")
    

    那么您就不必保存Parent 然后处理它的记录。

    【讨论】:

      【解决方案3】:

      这些是我的发现:

      1. Child 应该扩展 Parent 没有客观原因。在建模方面,我会改为使用一个抽象类,我们将其命名为 FamilyMember,然后是 ParentFirstBorn >SecondBorn 来自家庭成员。
      2. 向下转换问题将通过 (1) 解决
      3. Hibernate 不支持更新鉴别器值。这意味着,如果孩子长大成人,不再是孩子,而是父母。需要删除子记录并创建与父记录对应的新记录。这就是它的工作原理。一个孩子是一个孩子,直到它不再是一个孩子,然后该孩子记录被删除并创建一个新的非孩子记录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-16
        • 1970-01-01
        • 1970-01-01
        • 2014-04-22
        • 1970-01-01
        • 2016-08-13
        • 1970-01-01
        • 2014-10-17
        相关资源
        最近更新 更多