java 从数据库中选择 MappedSuperclass (Hibernate)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1427439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:31:16  来源:igfitidea点击:

Selecting MappedSuperclass from the database (Hibernate)

javahibernate

提问by pek

Problem

问题

I have a @MappedSuperclasscalled Data as the parent of every Entity in my database. It contains common attributes like Id etc. I then have an entity that extends Data which is also a @MappedSuperclassdue to common functionality of its subclasses. The mapping in my database is correct.

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

Here is an example of my hierarchy

这是我的层次结构的一个例子

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

And the tables are correctly mapped:

并且表被正确映射:

FullTimeEmployee  
PartTimeEmployee  
Store

Is there anyway to query the database for all Employee subclasses (FullTimeEmployee, PartTimeEmployee) as instances of Employee without referring the name of the subclasses in the query?

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

Something like

就像是

List<Employee> allEmployees = getAllEmployees();

The idea is that whenever I decide to create another subclass of Employee (i.e. AllDayEmployee) I will not have to change the query to include the name.

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



Solution

解决方案

So, as Gregorycorrectly pointed out, this is not possible with @MappedSuperclass. So I changed it into @Entity and, since I wanted to preserve a table for each subclass I used InheritanceType.JOINED.

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

So the above hierarchy is now

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

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

And the tables are still:

表格仍然是:

FullTimeEmployee  
PartTimeEmployee  
Store

So now, to get all Employees I simply call:

所以现在,要获得所有员工,我只需致电:

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

采纳答案by Gregory Mostizky

No if you are using @MappedSuperclass

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

The reason for this is that when you define base class as @MappedSuperclass, there is no table generated for the base class, instead all of the properties are replicated in the concrete tables. In your example only FullTimeEmployee, PartTimeEmployee and Store tables would exist.

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

If you want to be able to query for base class entities you need to select different mapping for base classes. Use @Inheritance annotation on the base class and select one of the 3 possible mapping strategies - SINGLE TABLE, TABLE PER CLASS or JOINED

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

回答by nsandersen

I seem to be able to do this (although using InheritanceType.JOINED) with hibernate 5.0.8, java 1.8.0_73 and Oracle 12c - either I am misunderstanding or maybe hibernate has changed..

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

I have the following hierarhcy:

我有以下层次结构:

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

And I can do the following HQL:

我可以执行以下 HQL:

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

which gives these 2 SQL statements:

这给出了这 2 个 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

and the warning

和警告

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

Not sure what they mean though, as this can be done with SQL as:

不知道他们的意思,因为这可以用 SQL 来完成:

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

(And you can also add limit/rownum clauses to that if you desire, although that gets a bit clunky:

(如果你愿意,你也可以添加 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

Not sure why hibernate shouldn't be able to do this - might suggest it to them.)

不知道为什么 hibernate 不应该能够做到这一点 - 可能会向他们建议。)

回答by Zoidberg

Yes

是的

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

But only, as the others have said here, if the Employee entity is mapped. You don't need to even map it to its' own table. See the mapping strategies in Hibernate.

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