Hibernate的表/子类继承策略的效率 [英] Efficiency of Hibernate's table-per-subclass inheritance strategy

查看:102
本文介绍了Hibernate的表/子类继承策略的效率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在考虑Hibernate管理的类层次结构的表格布局,而且每个子类技术的表格肯定是一般意义上最适合的。然而,通过逻辑思考,我对其性能有一些担忧,特别是随着子类数量的扩大。

I'm thinking about table layout for a Hibernate-managed class hierarchy, and certainly the table per subclass technique strikes me as the most appropriate in a general sense. However, thinking through the logic I have some concerns about its performance especially as the number of subclasses scale.

给出一个非常简短(和经典)的例子,让我们说你有以下类:

To give a very brief (and classic) example, let's say you have the following classes:

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映射等,只是假设它们是基本的明显的例子)。

(I'm eliding getters and setters and Hibernate mappings etc., just assume they're the basic obvious case).

这些实体的数据库表是有意义的,你得到很好的非规范化等等。但是,为了拉出一个动物,Hibernate会做什么查询?我可以想到可能发生这种情况的至少两种情况:

The database tables for these entities make sense, you get nice denormalisation and so on. However, what query does Hibernate do in order to pull out an individual animal? I can think of at least two cases where this might happen:


  1. 其他具有一对一(或一对一) -many)映射,例如 Human 类的 pet 字段。这将存储pkey,所以当Hibernate获取一个Human对象时,它也需要获取相应的 Animal 对象。当给予动物的pkey时,Hibernate使用什么查询(/ ies)来提取和解组实际的Animal数据,因为它可以驻留在 Cat Dog 表?

  2. HQL,例如Animal中的,其中name ='Rex'让我们假设名字是独一无二的)。这与上述类似,它允许您在超类表中标识一行,但您不知道要检查哪个子类表以获取更多详细信息。 HQL甚至允许您从抽象类中发出查询? (使用子类特定的东西很好地工作,例如, from CatChought> 5 )。

  1. Some other entity having a one-to-one (or one-to-many) mapping, such as a pet field of a Human class. This would store the pkey, so when Hibernate fetches a Human object it will need to fetch the corresponding Animal object too. When given the pkey of the animal, what query(/ies) will Hibernate use to extract and unmarshall the actual Animal data, given that it could reside in the Cat or Dog tables?
  2. HQL such as from Animal where name='Rex' (let's assume names are unique). This is similar to the above in that it lets you identify a row in the superclass table but you don't know which subclass table to inspect for further details. Does HQL even let you issue a query from an abstract class? (Using subclass specific stuff works nicely though, e.g. from Cat where miceCaught > 5).

我可以想到这样可以在SQL中完成的两种方式,而且看起来都不漂亮。一个是在给定pkey的每个子类表上运行存在查询,然后从返回一个命中的表加载。或者,Hibernate可以在所有表​​中执行一些可怕的联合查询加入 - 基本上模拟每个层次的方案,结果集将包括所有可能的子类的属性,并从子类表中返回 null 用于不相关的参数。后一种情况可能甚至需要添加一个合成鉴别器列,以便Hibernate可以知道哪个子类表实际返回该行,并因此知道应该分析哪些Java类。

I can think of two ways that this could be done in SQL and neither seems pretty. One is to run an exists query on each subclass table for the given pkey and then load from the table that returned a hit. Alternatively Hibernate could perform some horrible union query joining in all the tables - essentially simulating the table-per-hierarchy scheme in that the result set would include attributes for all possible subclasses with the individual selects from the subclass tables returning null for the irrelevant arguments. This latter case would probably even need to add a synthetic discriminator column so that Hibernate could know which subclass table actually returned the row and thus what Java class they should be parsed into.

如果您有具体类型的子类型,那么事情也会变得更美好:

Things get hairier too if you have subtypes of concrete types:

public class Greyhound extends Dog {
   float lifetimeRacingWinnings;
}

现在,对于给定的动物pkey, Dog Greyhound 表,这意味着我第一种手动检查对应于pkey获得了更多的困难。

Now for a given animal pkey, there may be valid rows in the Dog and Greyhound tables, meaning that my first approach of manually checking the class that corresponds to a pkey gets a lot tougher.

我非常担心的原因是我希望在类层次结构中使用这种方法,约有70个类,最大嵌套4-5级的链,所以执行所有这一切的联合查询可能会有可怕的性能。 Hibernate有没有任何技巧来保持这个性能呢?或者通过pkey加载对这些类之一的引用需要很长时间?

The reason I'm so concerned is that I will be wanting to use this approach on a class hierarchy with about 70 classes with a maximum nesting chain of 4-5 levels, so performing a union query on all of that is likely to have horrible performance. Does Hibernate have any tricks up its sleeve to keep this relatively performant? Or is loading a reference to one of these classes by pkey going to take a long time?

推荐答案

你会发现Hibernate将一个未知动物类型的查询写入一系列 LEFT JOIN 语句,每个子类一个。因此,随着子类数量的增加,查询将会减慢,并将尝试返回更广泛的结果集。所以你是正确的,它不能很好地与大类层次结构。

You'll find that Hibernate writes the query for an unknown animal type with a series of LEFT JOIN statements, one per subclass. So the query will slow as the number of subclasses increases, and will attempt to return an ever wider result set. So you are correct, it doesn't scale well with large class hierarchies.

使用HQL,是的,您可以直接查询子类,并访问其属性。那将会用一个单独的 INNER JOIN 来呈现。

With HQL, yes you can query the subclass directly, and access its properties. That will then be rendered with a single INNER JOIN.

我没有尝试过多级别的继承。如果上面还没有放弃你,建议你尝试一下,看看 - 你可以打开SQL调试输出,看看发送到数据库的内容,或者简单地分析你的数据库。

I haven't tried this with multiple levels of inheritance. If the above hasn't put you off yet, suggest you try it and see - you can turn on SQL debug output to see what is being sent to the database, or simply profile your database.

这篇关于Hibernate的表/子类继承策略的效率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆