【问题标题】:JPA/Hibernate - How is subclass type determined when querying by superclass?JPA/Hibernate - 超类查询时如何确定子类类型?
【发布时间】:2011-07-12 01:11:06
【问题描述】:

我刚刚注意到 Hibernate 中的这种行为,并发现它有点令人惊讶(以一种受欢迎的方式)。我有一个名为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 的直接映射(而是必须映射回来从propertiessyncItems)。执行此查询时,它是否与每个子类表进行连接?如果是这样,那不会使查询变得非常昂贵吗?

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

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

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

    Here你可以找到一个参考说明:

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

    三种可用策略中的每一种都有自己的优点和缺点(如果您更喜欢节省空间而不是时间,或者两者之间的妥协)。选择还取决于您将更频繁地对这些表执行的操作类型。在我粘贴的参考资料中,您会找到对每一个的相当好的和简单的解释。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-31
        • 2011-09-27
        • 2012-02-29
        • 2019-05-09
        • 2012-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多