Java和Hibernate的继承-更新时的类型转换

时间:2019-03-29 15:23:55

标签: java hibernate inheritance constructor

我的班级具有以下层次结构

@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是否可以在更新时进行修改?

要进一步处理,

我在子类中创建了contructor

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

但这会为子类型

创建新行
  Dtype       id  value
  Parent      1   "some value"
  FirstChild  2   "some value"

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

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

  

但是真正的问题是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
}

因此,休眠模式与Java行为相同:您无法更新Parent,必须为firstChild创建新记录并删除parent

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

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

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

答案 2 :(得分:1)

这些是我的发现:

  1. Child 应该扩展 Parent 没有客观原因。在建模方面,我将让一个抽象类将其命名为 FamilyMember ,然后将其命名为 Parent FirstBorn < / strong>和 SecondBorn 将从家庭成员中扩展过来。
  2. 垂头丧气的问题将由(1)解决
  3. 休眠不支持鉴别符值的更新。这意味着如果孩子长大了,不再是孩子,而是父母。子记录需要删除,并创建与父记录对应的新记录。这就是它的工作方式。一个孩子是一个孩子,直到不再是一个孩子,然后删除该孩子记录并创建一个新的非孩子。