从数据库中选择MappedSuperclass(Hibernate)

时间:2009-09-15 14:12:40

标签: java hibernate

问题

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

以下是我的层次结构的示例

@MappedSuperclass
Data  
 |  @MappedSuperclass
 +- Employee  
 |      |  @Entity
 |      +- FullTimeEmployee
 |      |  @Entity
 |      +- PartTimeEmployee
 |  @Entity
 +- Store

表格已正确映射:

FullTimeEmployee  
PartTimeEmployee  
Store

无论如何都要查询数据库中所有Employee子类(FullTimeEmployee,PartTimeEmployee)作为Employee的实例而不引用查询中的子类名称?

这样的东西
List<Employee> allEmployees = getAllEmployees();

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


解决方案

因此,正如Gregory正确指出的那样,@MappedSuperclass无法做到这一点。所以我将其更改为@Entity,因为我想为每个子类保留一个表,我使用了InheritanceType.JOINED

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

@MappedSuperclass
Data  
 |  @Entity
 |  @Inheritance(strategy=InheritanceType.JOINED)
 +- Employee  
 |      |  @Entity
 |      +- FullTimeEmployee
 |      |  @Entity
 |      +- PartTimeEmployee
 |  @Entity
 +- Store

表格仍然是:

FullTimeEmployee  
PartTimeEmployee  
Store

现在,为了得到所有员工,我只需致电:

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

3 个答案:

答案 0 :(得分:8)

否,如果您使用的是@MappedSuperclass

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

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

我有以下的hierarhcy:

@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为什么不能这样做 - 可能会向他们提出建议。)