为什么此HQL连接提取不返回期望的行

时间:2013-07-24 12:33:06

标签: sql hibernate hql

我有两个表:'publication'和'publication_translations'。

在hibernate中,我使用注释将翻译映射到具有@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注释中的错误

2 个答案:

答案 0 :(得分:0)

试试这个:

// 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

答案 1 :(得分:0)

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

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

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不会用它打印参数,所以我用查询中的params代替查询是否正常。

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

通过加入这两个表,Hibernate以某种方式不知道你想要映射状态字段的表。 Hibernate自动假设它只是DO中未知的另一列,因此它假定它是一个String。因为它是一个String,传入Object的setParameter失败并且可能输出[Object]而不是实际的toString()值。

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

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