使用Hibernate JPA(JPQL)的非多态查询

时间:2014-07-01 14:37:07

标签: hibernate jpa

我发布此问题+答案作为How to perform a non-polymorphic HQL query in Hibernate?的扩展。它还强调了Hibernate 4.1.x和4.3.5之间的行为变化,以及如果您的映射在非严格需要时包含@DiscriminatorColumn的错误。

我有一个具体的超类,患者,有一个具体的子类,截肢者。每个人都有自己的表('患者'截肢者'),Hibernate继承策略是JOINED。

首先,根据JPA规范,我选择了@DiscriminatorColumn区分截肢者与主要patient表中的香草患者,使用' P'对于香草患者和' A'截肢者:

@Entity
@Table(name="patient")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("P")

public class Patient {...

@Entity
@Table(name="amputee")
@DiscriminatorValue("A")

public class Amputee extends Patient {...

选择所有患者的JPQL查询,包括香草和截肢者(工作正常):

select p from Patient p

JPQL查询只选择截肢者,而不是香草(工作正常):

select a from Amputee a

JPQL查询仅使用TYPE运算符选择vanilla( -amputee)患者:

select p from Patient p where type(p) <> Amputee

...适用于Hibernate 4.1.3,但不适用于4.3.5(这些只是我测试过的两个版本,也可能是其他版本)。

4.1.3已经生成了一些时髦的连接和切换/案例SQL,但至少有效。 4.3.5生成无效的SQL ,至少在使用上述映射时。这里生成的WHERE子句带有错误条件:

where case when patient0_1_.id is not null then A when patient0_.id is not null then 'P' end<>'A'

你可以看到&#34;然后A&#34; bit应该在单引号中有A,但不是,所以SQL失败。我在Hibernate日志中通过一个模糊的警告引出了解决方案:

WARN HHH000457: Joined inheritance hierarchy [cellnostics.model.Patient] defined explicit @DiscriminatorColumn. Legacy Hibernate behavior was to ignore the @DiscriminatorColumn. However, as part of issue HHH-6911 we now apply the explicit @DiscriminatorColumn. If you would prefer the legacy behavior, enable the hibernate.discriminator.ignore_explicit_for_joined setting (hibernate.discriminator.ignore_explicit_for_joined=true)

事实证明,对于SINGLE_TABLE或JOINED层次结构,Hibernate不需要@DiscriminatorColumn:它会在所有相关表中发出体操连接+案例语句。但是,如果您遵循JPA建议并且执行在此类映射中指定@DiscriminatorColumn,则Hibernate会在4.3.5版中生成无效SQL ,同时生成笨重但至少在4.1.3中使用SQL。

您可以在Hibernate JIRA: HHH-6911上了解有关@DiscriminatorColumn问题的更多信息。

因此,解决方案是没有@DiscriminatorColumn s的映射:

@Entity
@Table(name="patient")
@Inheritance(strategy=InheritanceType.JOINED)

public class Patient {...

@Entity
@Table(name="amputee")

public class Amputee extends Patient {...

...对于原始的非多态查询:

select p from Patient p where type(p) <> Amputee

生成正确的SQL并返回正确的结果:

where case when patient0_1_.id is not null then 1 when patient0_.id is not null then 0 end<>1

0 个答案:

没有答案