JPQL 无法创建继承层次结构的基类(抽象)对象列表

Posted

技术标签:

【中文标题】JPQL 无法创建继承层次结构的基类(抽象)对象列表【英文标题】:JPQL unable to create a list of objects of base class (abstract) of an inheritance hierarchy 【发布时间】:2015-09-02 07:50:31 【问题描述】:

我们有一个继承层次结构,如下所示:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQuery("select NEW package.BaseClass(bc.field1, bc.field2) from BaseClass b")
public abstract BaseClass 
   public BaseClass(int field1, String field2) 
   


@Entity
public SubClass1 extends BaseClass 

和类似的 SubClass2

现在我面临的问题是这里的@NamedQuery 语法,它不允许我创建 List 对象,因为它无法使用构造函数实例化 BaseClass。那么任何人都可以建议如何解决这个问题,同时将命名查询留在基类本身中?

或者请告诉我是否有办法在选择中排除列

select bc.*Field3 from BaseClass

或者类似的语法会阻止延迟加载我在这种情况下不需要的关联字段3?

【问题讨论】:

由于集合是lazy加载的,执行查询不会加载它。只需从 BaseClass b 中使用 select b。 @JBNizet,首先,一个小的更正,我已经更新了问题,这不是我想要避免的集合,而是一个关联。但即使没有访问此关联对象,它也会在延迟加载关联的查询中触发。刚才确认了。不幸的是,我不确定是否可以在此处发布与代码相关的信息,否则我可以以触发查询的形式显示证明。我正在为父对象中的另一个关联对象使用 JOIN FETCH,但不需要的查询似乎是针对另一个关联对象,而不是我正在使用 JOIN FETCH 的那个。 【参考方案1】:

你在这里以一种奇怪的方式使用了一些东西。

首先,JPQL 构造函数表达式通常用于非实体类。您可以拥有一些具有两个字段(field1field2)和匹配构造函数的非实体类,并在您的 @NamedQuery 中使用它代替 package.BaseClass,它应该可以工作。我没有看到在这里使用实体类的意义。如果您希望获得仅初始化 field1field2BaseClass 实体列表,那么它不是这样工作的。但是select bc.field1, bc.field2 from BaseClass b 会起作用,但它会给出一个元组,而不是实体。

此外,@OneToOne@ManyToOne 默认情况下是急切获取的,因此这可能是您看到的额外查询触发的原因。将其明确设置为FetchType.LAZY,应该没问题。

关于这个

如何解决这个问题,同时将命名查询留在基类本身中

您不必将命名查询保留在基类中,您可以将它放在您想要的任何实体中。一个经常使用的选项是拥有一个“假”实体,它将所有命名查询保存在一个地方。以this answer 为例。

【讨论】:

对于我的应用程序,我不确定放置 FetchType.LAZY 是否会避免触发查询,因为我确实看到了查询,但让我假设它是由于我的应用程序特定的其他原因而发生的。现在我的问题是我可以使这个 FetchType.LAZY 特定于所讨论的查询,而不是把它放在注释中吗? Hibernate 是我的 JPA 提供者。 我不确定您是否可以在查询级别将渴望关联覆盖为惰性,至少我不知道如何。也许最好的选择是创建一个仅包含您需要的字段的非实体类,并在构造函数表达式中使用它(当然,如果它适合您的其余代码)。

以上是关于JPQL 无法创建继承层次结构的基类(抽象)对象列表的主要内容,如果未能解决你的问题,请参考以下文章

C++ 虚继承的对象模型

多个类型/类的HQL查询

Java Review (十面向对象----抽象类)

Java Review (十面向对象----抽象类)

面向对象四大特性

当涉及部分虚拟继承时,这是计算创建的基类对象数量的正确方法吗?