从数据库中选择 MappedSuperclass (Hibernate)

Posted

技术标签:

【中文标题】从数据库中选择 MappedSuperclass (Hibernate)【英文标题】:Selecting MappedSuperclass from the database (Hibernate) 【发布时间】:2009-09-15 14:12:39 【问题描述】:

问题

我有一个名为 Data 的@MappedSuperclass 作为我数据库中每个实体的父级。它包含 Id 等通用属性。然后我有一个扩展 Data 的实体,由于其子类的通用功能,它也是 @MappedSuperclass。我的数据库中的映射是正确的。

这是我的层次结构示例

@MappedSuperclass 数据 | @MappedSuperclass +- 员工 | | @实体 | +- 全职员工 | | @实体 | +- 兼职员工 | @实体 +- 商店

并且表格已正确映射:

全职员工 兼职的员工 店铺

是否可以在数据库中查询所有 Employee 子类(FullTimeEmployee、PartTimeEmployee)作为 Employee 的实例而不在查询中引用子类的名称?

类似

List<Employee> allEmployees = getAllEmployees();

这个想法是,每当我决定创建另一个 Employee 子类(即 AllDayEmployee)时,我都不必更改查询以包含名称。


解决方案

因此,正如Gregory 正确指出的那样,@MappedSuperclass 不可能做到这一点。所以我把它改成了@Entity,因为我想为每个使用InheritanceType.JOINED的子类保留一个表。

所以上面的层次结构现在是

@MappedSuperclass 数据 | @实体 | @Inheritance(策略=InheritanceType.JOINED) +- 员工 | | @实体 | +- 全职员工 | | @实体 | +- 兼职员工 | @实体 +- 商店

桌子还在:

全职员工 兼职的员工 店铺

所以现在,我只需调用所有员工:

entityManager.createQuery("from Employee").getResultList();

【问题讨论】:

如果我需要两个不同的@SequenceGenerator 用于 FullTimeEmployee 和 PartTimeEmployee(我正在使用 Oracle 序列)怎么办?作为一个实体,我必须在 Employee 类上指定@Id 【参考方案1】:

如果您使用的是@MappedSuperclass,则否

原因是当您将基类定义为@MappedSuperclass 时,没有为基类生成表,而是将所有属性复制到具体表中。在您的示例中,仅存在 FullTimeEmployee、PartTimeEmployee 和 Store 表。

如果您希望能够查询基类实体,则需要为基类选择不同的映射。在基类上使用 @Inheritance 注释并选择 3 种可能的映射策略之一 - SINGLE TABLE、TABLE PER CLASS 或 JOINED

【讨论】:

【参考方案2】:

是的

FROM Employee WHERE Employee.<employee only properties> = someValue

但是,正如其他人在这里所说,如果 Employee 实体被映射。您甚至不需要将其映射到它自己的表。请参阅 Hibernate 中的映射策略。

【讨论】:

+1 是的。在 Hibernate 中,你可以选择一个抽象类,你也会得到所有的子类。给出的示例是查询对象,这将返回整个数据库! :-) 鉴于 Employee 是一个具有 @MappedSuperclass 注释的抽象类,我想获取 Employee 的所有子类实例。 “来自员工”查询引发 QuerySyntaxException:员工未映射“ 请查看我的回答,了解为什么它不适用于@MappedSuperclass @Gregory:我假设 Employee 被映射为一个实体。我将更新我的回复以反映这一点。 我还更新了我的问题,以便更清楚地知道哪个是哪个【参考方案3】:

我似乎能够使用 hibernate 5.0.8、java 1.8.0_73 和 Oracle 12c 来做到这一点(尽管使用 InheritanceType.JOINED)——要么我误解了,要么 hibernate 已经改变了..

我有以下层次结构:

@MappedSuperclass
@Inheritance(strategy=InheritanceType.JOINED)
CommonRoot
 |
 |  @MappedSuperclass
 +- Mapped
        |  @Entity(name="Concrete1")
        |  @Table(name="CON1")
        +- Concrete1
        |
        |  @Entity(name="Concrete2")
        |  @Table(name="CON2")
        +- Concrete2

我可以执行以下 HQL:

SELECT entityId FROM com.hibernatetest.Mapped ORDER BY entityId ASC

给出这两条 SQL 语句:

select concrete2x0_.entityId as col_0_0_ from CON2 concrete2x0_ order by concrete2x0_.entityId ASC
select concrete1x0_.entityId as col_0_0_ from CON1 concrete1x0_ order by concrete1x0_.entityId ASC

和警告

WARN: HHH000180: FirstResult/maxResults specified on polymorphic query; applying in memory!

但不确定它们的含义,因为这可以使用 SQL 来完成:

(select entityId from CON2
union all
select entityId from CON1)
order by entityId ASC

(如果你愿意,你也可以添加limit/rownum子句,虽然这有点笨拙:

select * from (
(select * from (select entityId from CON2 order by entityId ASC) where rownum <= 10)
UNION ALL
(select * from (select entityId from CON1 order by entityId ASC) where rownum <= 10)
) where rownum <= 10 order by entityId ASC

不知道为什么 hibernate 不能这样做 - 可能会向他们建议。)

【讨论】:

以上是关于从数据库中选择 MappedSuperclass (Hibernate)的主要内容,如果未能解决你的问题,请参考以下文章

doctrine2 映射覆盖从 MappedSuperclass 继承的 inversedBy 字段。

春季是不是有 mongoDB 的 @MappedSuperclass 等效注释?

@MappedSuperclass的用法

Hibernate中的Entity类之间的继承关系之一MappedSuperclass

在 Zend 框架 2 中使用 MappedSuperclass 的 Doctrine 2 多对多

注解@MappedSuperclass的作用