【问题标题】:Selecting MappedSuperclass from the database (Hibernate)从数据库中选择 MappedSuperclass (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

标签: java hibernate


【解决方案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 不能这样做 - 可能会向他们建议。)

    【讨论】:

      猜你喜欢
      • 2020-11-23
      • 1970-01-01
      • 2012-01-01
      • 2011-11-18
      • 1970-01-01
      • 2019-10-25
      • 2013-06-22
      • 2019-02-21
      • 1970-01-01
      相关资源
      最近更新 更多