【发布时间】: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 而不是其他东西,据我所知,它没有从 syncItems 到 properties 的直接映射(而是必须映射回来从properties 到syncItems)。执行此查询时,它是否与每个子类表进行连接?如果是这样,那不会使查询变得非常昂贵吗?
所以是的,只是想知道这里的幕后发生了什么。
【问题讨论】: