在使用Joined继承时,hibernate如何知道要创建哪个子类

时间:2012-01-26 20:13:39

标签: hibernate inheritance

如果我有

@Inheritance(strategy = InheritanceType.JOINED)
Organization{
}

Account extends Organization{
   private Organization organization
}

Client extends Organization{
   private Organization organization
}

User {
   private Organization organization
}

当我调用userDAO.get(1)并返回User的实例时,hibernate如何知道给我一个Account而不是Client的实例?

3 个答案:

答案 0 :(得分:2)

没有鉴别器

Hibernate对每个子表执行OUTER JOIN

SELECT *,
case
    when a.id is not null then 0
    when c.id is not null then 1
    when u.id is not null then 2
end as clazz
FROM Organization o
    OUTER JOIN Account a
    OUTER JOIN Client c
    OUTER JOIN User u

通过查看实际返回的OUTER JOIN来确定实际类型。显然,Account只有一个表,ClientUser持有一个具有相同id的记录 - 这表示实际类型。这就是尴尬的case / when所做的。

带鉴别器

如果存在鉴别器列,则仍然需要OUTER JOIN,但更容易确定实际类型,因为它明确存储在数据库中。没有case / when魔术。

摘要

正如您所看到的,这种继承策略效率很低。当您明确要求给定的子类型时,它会好得多,因为Hibernate将仅使用一个表执行JOIN

另见:

答案 1 :(得分:1)

对于每个记录,hibernate可以在主表中存储一个附加(鉴别器)列,指示使用哪种类型。

答案 2 :(得分:0)

注意:仅适用于SINGLE_TABLE策略,请参阅@Tomazs对JOINED策略的回复。

Hibernate将显式子类存储为数据库中的某种形式的枚举,通常作为字符串值。您可以使用@DescriminatorColumn注释设置此列的名称,然后在子类上使用@DiscriminatorValue注释。当Hibernate在数据库中存储Account时,任何特定于Client的行仍然存储为Account但设置为null,并且DiscriminatorColumn设置为"Account"。然后,当组织被反序列化时,Hibernate会查看DiscriminatorColumn,看到OrganizationAccount,并返回该类型的对象。

DescriminatorColumn可以更改为使用其他类型的数据,例如。不是字符串,使用columnDefinition参数。默认情况下,此列的名称为DTYPE,而没有DiscriminatorValue的类的值是该类的名称。