我正在考虑Hibernate管理的类层次结构的表布局,并且从某种意义上说,每个子类的表技术肯定是最合适的。但是,仔细考虑逻辑,我对它的性能有些担忧,尤其是随着子类数量的增加。
举一个非常简短(经典)的示例,假设您具有以下类:
public abstract class Animal {
int pkey;
String name;
}
public class Dog extends Animal {
long numSlippersChewed; // int is not large enough...
}
public class Cat extends Animal {
short miceCaught; // ... but here int is far bigger than required :-)
}
(我在取消getter和setter和Hibernate映射等,只是假设它们是基本的显而易见的情况)。
这些实体的数据库表很有意义,您可以很好地进行非规范化等等。但是,Hibernate为了提取单个动物会做什么查询?我至少可以想到两种情况:
pet
字段Human
。这将存储pkey,因此,当Hibernate提取Human对象时,它也需要提取相应的Animal
对象。当给定动物的pkey时,假设它可以驻留在Cat
或Dog
表中,Hibernate将使用什么查询来提取和解组实际的动物数据?from Animal where name='Rex'
(假设名称是唯一的)。这与上面的类似,因为它使您可以标识超类表中的一行,但您不知道要检查哪个子类表以了解更多详细信息。HQL甚至可以让您from
向抽象类发出查询吗?(例如,使用子类特定的东西效果很好from Cat where miceCaught > 5
)。我可以想到两种可以在SQL中完成的方法,而且看起来都不是很漂亮。一种是exists
在每个子类表上查询给定的pkey,然后从返回命中的表中加载。替代地,Hibernate可以在所有表中执行一些可怕的联合查询-
本质上模拟逐级表方案,因为结果集将包括所有可能的子类的属性,并且子类表中的各个选择返回null
不相关的参数。后一种情况甚至可能需要添加一个综合的鉴别符列,以便Hibernate知道哪个子类表实际上返回了该行,从而知道应该将它们解析为哪个Java类。
如果您有具体类型的子类型,事情也会变得更加棘手:
public class Greyhound extends Dog {
float lifetimeRacingWinnings;
}
现在,对于给定的动物pkey,Dog
and
Greyhound
表中可能存在有效的行,这意味着我手动检查与pkey相对应的类的第一种方法变得更加困难。
我如此担心的原因是,我将要在具有约70个类的类层次结构中使用此方法,最大嵌套链为4-5级,因此对所有这些执行联合查询可能会很 可怕
性能。Hibernate是否有技巧来保持这种相对出色的表现?还是通过pkey加载对这些类之一的引用会花费很长时间?
您会发现,Hibernate使用一系列LEFT JOIN
语句(每个子类一个)来编写未知动物类型的查询。因此,查询将随着子类数量的增加而变慢,并将尝试返回越来越大的结果集。所以您是正确的,它在大型类层次结构中无法很好地扩展。
使用HQL,可以,您可以直接查询子类并访问其属性。然后将使用单个渲染INNER JOIN
。
我没有尝试使用多个继承级别。如果上述方法尚未解决问题,建议您尝试一下然后看看-
您可以打开SQL调试输出以查看发送到数据库的内容,或者只是对数据库进行概要分析。
主要内容:连接策略示例在按类表策略中,为每个子实体类生成一个单独的表。 与连接策略不同,在按类表策略中不会为父实体类生成单独的表。 以下语法表示按类表策略 - 连接策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(
主要内容:单表策略示例单表策略是定义继承实现的最简单有效的方法之一。 在这种方法中,多个实体类的实例仅作为属性存储在单个表中。 以下语法表示单个表策略 - 单表策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(它是
我有一个实体照片映射在JPA/Hibernate,有三个不同的孩子(PhotoSpot,PhotoSecteur,PhotoVoie)。我使用了@继承(策略=继承类型。JOINED),一切工作正常的持久化方法,但我不能设法使其工作时,我想删除的照片之一。 我试图通过从父类中删除一个元素来删除一张照片,但我不知道这是否可行。我看了所有其他关于同一主题的帖子,我认为问题可能来自我的子实体有一个@man
由于某些原因,我无法使Hibernate继承策略=InheritanceType.Joint&onetoMany的组合工作。以下是这些实体。 @实体
主要内容:连接策略示例在连接策略中,为每个实体类生成一个单独的表。 每个表的属性都与主键连接。 它消除了字段字重复的可能性。 以下语法表示连接的策略: - 连接策略示例 在这个例子中,我们将员工分为活跃员工和退休员工。 因此,子类和继承父类的和字段。 现在,按照以下步骤创建JPA项目 - 第1步: 在包下创建一个根实体类并指定所有必需的属性和注释。 文件:Employee.java - 第2步: 在包下创建实体类(它是
当我只有product类和两个用继承策略扩展product的类时,单表(product- 必须在根实体中定义鉴别器列,它将在子类com中被忽略。实例演示。实体电子学 产品类别 电子类: 智能手机类别: 我想把电子学课分成两个不同领域的实体。