2009-10-07 66 views
2

我有3个非抽象的持久化类。 MyClubUser和HisClubUser类继承自User类。对于这些类,我使用每个子类策略的一个表,即@Inheritance(strategy = InheritanceType.JOINED)Hibernate继承策略和为什么

我观察到的是,当我在用户类上进行查询时,生成的SQL使用左外连接HisClubUser和MyClubUser。为什么Hibernate会这样做[加入其他表]我只关心用户的问题?我的观点是,即使数据被检索到,但如果返回了User实例,我将无法访问MyClubUser或HisClubUser中的这些属性。此外,这是否会导致额外的开销,而不是只查询用户表而没有左外连接的查询?

谢谢

回答

5

休眠总是返回实际类型的持久实体。如果您存储了“MyClubUser”,它将作为“MyClubUser”返回,而不是“用户”。原因很明显 - 如果Hibernate将“MyClubUser”作为“用户”返回,并且您要再次坚持,则会失去“MyClubUser”中定义的所有其他属性。

为了做到这一点,Hibernate需要知道实际类型是什么。对于InheritanceType.JOINED策略,唯一的办法是在继承层次结构中检查全部表(在技术上,它是当前级别或低于当前级别的表以及当前树分支中当前级别以上的所有表)。所以,如果你有这样一个层次结构:

  Root 
     / \ 
     Node1 Node2 
    / \ 
    Node11 Node12 

和你想从根本选择,Hibernate会做所有表外连接。如果您从Node1中选择,Hibernate将在Node1和Root上进行内连接,并在Node11和Node12上执行外连接。 Node2不会被触及,因为它不是Node1的后代。

就外连接开销而言 - 是的,肯定有一个开销,但这是您为加入策略付出的代价。你可以使用鉴别器来避免这种情况,但是它带有自己的副作用。这种开销是否显着取决于层次结构的深度和分布,索引以及其他许多事情。聆听KLE的建议并描述它。

+0

+1非常感谢这些细节,他们明确了为什么我的原始SimpleUser提案不适用于InheritanceType.JOINED。我从答案中删除了这部分内容,而不是误导任何人。 – KLE 2009-10-08 09:41:43

2

你在User上查询,所以Hibernate会执行一个'多态查询'。由于MyClubUser和HisClubUser本质上是User对象(它们继承自User),因此Hibernate也会检索这些类型的用户。

4

为什么Hibernate会这样[加入其他表]我关注的只是用户?

因为所有HisClubUser也是用户的有效的情况下,这是合乎逻辑的,当你问用户检索这些。

我的观点是,即使数据被检索到,但我无法在MyClubUser或HisClubUser中访问这些属性,因为返回了User实例。

你确定吗?检查(例如在调试中)返回的有效类,它应该是子类。因此可以进行向下转换,并且可以访问这些属性。

此外,这是否会导致额外开销与查询相比,它只是查询没有左外连接的用户表?

是的,额外的连接有开销。这可能很重要或不重要:我建议你在你的具体情况下进行测试。

+1

+1。但是,您应该删除SimpleUser的建议,因为它不会帮助;我在我的回答中解释了“为什么”。 – ChssPly76 2009-10-07 17:27:26

+0

@ ChssPly76谢谢。我已阅读你的答案,现在我明白了“为什么”。你是对的:-) – KLE 2009-10-08 09:39:23

+0

谢谢你们......我现在明白了。我现在正在做的是MyClubUser和HisClubUser将与用户建立1对1的关系,而不是从用户继承。要访问MyClubUSer和HisClubUser中的其他属性,我会再次查询。用户用于登录。大多数时候使用特定的类。偶尔会读取用户中的属性。 @KLE我相信。查询只返回用户,这是有道理的。如果可以下载,那么用户必须继承MyClubUser和HisClubUser,这是不可能的。 – thlim 2009-10-10 04:50:11