Hibernate继承策略及其原因

Hibernate继承策略及其原因,hibernate,inheritance,Hibernate,Inheritance,我有3个非抽象的可持久化类。MyClubUser和HisClubUser类继承自用户类。对于这些类,我为每个子类策略使用一个表,即@heritance(strategy=InheritanceType.JOINED) 我所观察到的是,当我对用户类进行查询时,生成的SQL使用左外连接HisClubUser和MyClubUser。为什么Hibernate会这样做[加入其他表],而我只关心用户?我的观点是,即使检索到数据,如果返回了用户实例,我也无法访问MyClubUser或HisClubUser中的

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

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


感谢您查询用户,所以Hibernate将执行“多态查询”。由于MyClubUser和HisClubUser本质上是用户对象(它们从用户继承),Hibernate也将检索此类用户

为什么Hibernate会这样做[加入其他表],而我只关心用户

因为所有HisClubUser都是用户的有效实例,所以在请求用户时检索这些实例是合乎逻辑的

我的观点是,即使检索到数据,如果返回了用户实例,我也无法访问MyClubUser或HisClubUser中的这些属性

你真的确定吗?检查(例如在debug中)返回的有效类,它应该是子类。因此,向下浇铸是可能的,并且可以访问属性

另外,与只查询用户表而不查询左外部联接的查询相比,这是否会导致额外的开销


是的,额外的连接有开销。它可能很重要,也可能不重要:我建议您在特定的情况下测试它。

Hibernate始终返回持久化实体的实际类型。如果您存储了“MyClubUser”,它将返回为“MyClubUser”,而不是“User”。原因很清楚——如果Hibernate将“MyClubUser”返回为“User”,并且您再次将其持久化,那么您将丢失“MyClubUser”中定义的所有其他属性

为了做到这一点,Hibernate需要知道实际的类型是什么。对于
InheritanceType.JOINED
策略,找到答案的唯一方法是检查继承层次结构中的所有表(从技术上讲,它是当前树分支中处于或低于当前级别的所有表加上高于当前级别的所有表)。因此,如果您有如下层次结构:

           Root
          /   \
      Node1  Node2
      /   \
   Node11 Node12
当您试图从根目录中选择时,Hibernate将对所有表进行外部联接。如果您从Node1中选择,Hibernate将在Node1和Root上进行内部连接,在Node11和Node12上进行外部连接。节点2不会被触摸,因为它不是节点1的后代


至于外部连接开销——是的,肯定有开销,但这是您为连接策略付出的代价。您可以使用鉴别器来避免这种情况,但这会带来自身的副作用。这种开销是否显著取决于层次结构、索引和许多其他内容的深度和范围。倾听KLE的建议,并对其进行简介。

+1。但是,您可能应该删除SimpleUser建议,因为它不会有帮助;我已经在回答中解释了“为什么”。@chssly76谢谢。我读了你的答案,现在我完全明白了“为什么”。你说得对:-)谢谢大家。。。我现在明白了。我现在做的是MyClubUser和他的Clubuser将与用户建立1对1的关系,而不是从用户继承。要访问MyClubUSer和HisClubUser中的其他属性,我将再次查询。用户已登录。大多数情况下,都会使用特定的类。偶尔会读取用户中的属性@我敢肯定。查询只返回有意义的用户。如果向下转换是可能的,那么用户必须继承MyClubUser和他的Clubuser,这是不可能的。+1非常感谢这些详细信息,他们清楚地说明了为什么我最初的SimpleUser方案不能与InheritanceType.JOINED一起使用。我从我的答案中删除了这一部分,不是为了误导任何人。