2

我有两个表:“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

出版.java:

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

PublicationTranslation.java

@ManyToOne
private Publication publication;

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

4

2 回答 2

1

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

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

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);

这在没有“左连接提取”的情况下工作正常,但在我添加它后停止工作,所以我得出结论“左连接提取”不起作用。

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

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

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

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

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

于 2013-07-25T12:46:40.747 回答
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
于 2013-07-24T14:06:03.023 回答