JPA / Hibernate - 超类查询时如何确定子类类型?

时间:2011-07-12 01:11:06

标签: java hibernate jpa

我刚刚注意到Hibernate中的这个bevahior并且发现它有点令人惊讶(以一种受欢迎的方式)。我有一个名为SyncItem的实体类型,它作为许多其他实体的超类。继承策略设置为InheritanceType.JOINED,因此超类中的所有字段都有一个表,子类表只包含子类中添加的任何字段,以及返回超类表的引用。

例如,我的SyncItem表格如下:

mysql> describe syncItems;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| hidden     | bit(1)       | NO   |     | NULL    |                |
| title      | varchar(255) | NO   |     | NULL    |                |
| createDate | datetime     | NO   |     | NULL    |                |
| modifyDate | datetime     | YES  |     | NULL    |                |
| deleteDate | datetime     | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

如果我有一个Property子类,它可能会得到一个像:

这样的表
mysql> describe properties;
+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| syncId       | bigint(20)   | NO   | PRI | NULL    |       |
| propertyCode | varchar(255) | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

现在我有十几个不同的子类,让我感到惊讶的是我有一个类似的查询:

@NamedQuery(
    name="SyncItem.findByTitle", 
    query="SELECT s FROM SyncItem s WHERE s.title = :title")

当我写这篇文章的时候,我希望因为我从SyncItem中选择,我只会得到超类表中包含的信息(即我会得到一个SyncItem实例,而不是一个Property实例)。但是,当我运行它时,我发现查询实际上返回了正确的子类实​​例。这很好,因为它使许多事情更容易实现。

但是,我想知道,JPA / Hibernate如何管理这个子类?它无法知道给定的标题是否会映射到Property而不是其他内容,而且据我所知,它没有从syncItemsproperties的直接映射(相反,它必须从properties映射回syncItems)。在执行此查询时,它是否与每个子类表进行连接?如果是这样那么这不会使查询非常昂贵吗?

所以是的,只是想知道幕后发生了什么。

2 个答案:

答案 0 :(得分:4)

是的,它为每个子表执行加入。它很昂贵,但您可以使用其他两种策略来映射继承。

Here你可以找到一个参考文献:

  

联合策略通常是继承模型中最慢的。   检索任何子类需要一个或多个数据库连接,以及   存储子类需要多个INSERT或UPDATE语句

3种可用策略中的每一种都有其自身的优点和缺点(如果您希望节省空间而不是时间,或两者之间的妥协)。选择还取决于您将更频繁地对这些表执行的操作类型。在我粘贴的参考文献中,你会发现每个参考文献都有一个相当简单的解释。

答案 1 :(得分:1)

我相信它会加入所有子类。它可能比没有连接更昂贵,但没有那么多,因为密钥被索引,只有一个表将包含所需的密钥。使用继承将不可避免地有一些开销。

您可以查看SQL日志输出以便自己查看。