【问题标题】:Why is this HQL join fetch not returning expecting rows为什么这个 HQL 连接提取不返回预期的行
【发布时间】:2013-07-23 22:31:10
【问题描述】:

我有两个表:“publication”和“publication_translations”。

在休眠中,我使用注释将翻译映射到带有@ManyToOne 的发布对象。

在 DAO 层中,我使用查询来获取所有发布,如下所示:

from publication p where application_id = :applicationId

现在我想将翻译加入到应用程序对象中,例如:

from publication p left outer join fetch p.translations pt where application_id = :applicationId

这会产生如下 SQL 查询:

  select
        publicatio0_.id as id25_0_,
        translatio1_.id as id26_1_,
        publicatio0_.application_id as applica17_25_0_,
        publicatio0_.url as url25_0_,
        translatio1_.language as language26_1_,
        translatio1_.name as name26_1_,
        translatio1_.publication_id as publicat4_26_1_,
        translatio1_.id as id0__ 
    from
        publication publicatio0_ 
    left outer join
        publication_translation translatio1_ 
            on publicatio0_.id=translatio1_.id 
    where
        and application_id=180;

当我直接在 MySQL 中运行此查询时,它会按预期返回行。但是 session.list() 返回的 List 以某种方式保持为空。

当翻译不存在时,Hibernate 似乎会丢弃行。 (正如您对内连接的期望,但不是左外连接..

为什么会这样?我错过了什么吗?

顺便说一句。我这样做的原因是因为我想在声明特定语言的 hql 子句中添加 where 或 with,这样您就可以获取特定语言的翻译。但我简化了案例来说明问题。最终结果将类似于:

from publication p join fetch p.translations pt where (pt.language = :language or pt.language is null) and application_id = :applicationId

Publication.java:

@OneToMany(mappedBy = "publication")
private List<PublicationTranslation> translations; 

PublicationTranslation.java

@ManyToOne
private Publication publication;

编辑:在类上添加注释: Edit2:在 Publication.java 上的注释中更改错误

【问题讨论】:

  • 您的查询对我来说很好。您能否发布您的 @OneToMany@ManyToOne 映射。另外,为了确定,select p from publication p left join fetch p.translations pt where p.application_id = :applicationId 做得更好吗?
  • 不,我尝试使用“select”、“left join”、“join fetch”和没有“fetch”。
  • 为什么是 session.list()?我想你会得到一个发布对象并通过调用publication.getTranslation()来检索翻译
  • 那么,您是通过主键列加入的吧?外键类似于ALTER TABLE publication_translation ADD FOREIGN KEY (id) REFERENCES publication (id)?
  • @Hippoom:我想要一份正确语言的出版物列表。不是一个对象。

标签: sql hibernate hql


【解决方案1】:

试试这个:

// Publication.java
@OneToMany(mappedBy = "publication")
private List<PublicationTranslation> translations; 

// PublicationTranslation.java
@ManyToOne
@JoinColumn(columnName="publication_id", referencedColumnName="id")
private Publication publication;

或者,如果你真的需要通过pk加入(看起来是个错误):

// PublicationTranslation.java
@ManyToOne
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
private Publication publication;

public void setPublication(Publication publication) {
   this.publication= publication;
   this.id = publication.getId();
}

那么下面的 HQL 应该可以解决问题:

select p from publication p 
  left join fetch p.translations pt 
 where p.application_id = :applicationId

【讨论】:

  • 我的错,确实是映射到FK上的。不幸的是,它并没有解决问题。只要您省略查询的连接提取部分,映射就可以在两种方式中正常工作。
  • 所以您是说您已将原始映射更改为我在此处描述的内容,但仍然无法正常工作?您介意使用映射更改后生成的 SQL 查询来更新您的问题吗?
【解决方案2】:

我终于明白了。我会分享答案。

问题在于我遗漏的查询中的额外属性。完整的查询如下所示:

from publication p left join fetch p.translations pt where (pt.language = :language or pt.language is null) and p.application.id = :applicationId and state = :state and active = true and spsUpload = false

query.setParameter("state", PublicationState.DONE);

没有'left join fetch'这工作正常,但在我添加它后停止工作,所以我得出结论'left join fetch'不起作用。

我在控制台中打印了生成的 SQL。不幸的是,Hibernate 没有用它打印参数,所以我替换了查询中的参数以查看查询是否正常。

实际上是参数'state'的值搞砸了,但没有办法真正看到它(有吗?)。

通过连接这两个表,Hibernate 不知何故不知道您要将状态字段映射到哪个表。 Hibernate 自动假定它只是你的 DO 中未知的另一列,因此它假定它是一个字符串。因为它是一个字符串,所以传入 Object 的 setParameter 失败,可能会输出 [Object] 而不是实际的 toString() 值。

那么我学到了什么: 1. Hibernate 不会打印查询中的替代项,因此您不能假设它们的值。 2. 共享一段简化代码时,准确运行该代码以查看结果,即使您完全确信问题出在其他地方。

无论如何,谢谢你的帮助,否则我不会找到它..

【讨论】:

  • 这里要学习的两个教训是:1. 始终在字段前面加上实体别名p.state = :state and p.active = true and p.spsUpload = false,2. 使用指定参数类型。 query.setString("state", PublicationState.DONE.toString())
  • 这本来可以避免麻烦(这根本不是什么傻事,hibernate可以在查询中使用枚举类型,并且默认情况下它将枚举类型映射到其序数,除非您将字段映射为@Enumerated(EnumType.STRING).
  • 关于打印参数(有!):stackoverflow.com/questions/1710476/…
猜你喜欢
  • 2021-08-24
  • 1970-01-01
  • 2019-12-26
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多