Hibernate - 使用集合进行多表连接查询

4

我在使用Hibernate进行查询时遇到了问题,当查询中涉及多个集合的连接时,无法返回正确填充的对象图。

例如:

    String sql = "select distinct changeset " +
            "from Changeset changeset " +
            "join fetch changeset.changeEntries as changeEntry " +
            "join fetch changeEntry.repositoryEntity as repositoryEntity " +
            "join fetch repositoryEntity.repository as repository " +
            "where repository.connectionName = :connectionName";
  • 一个Changeset有多个ChangeEntries
  • 一个ChangeEntry有一个RepositoryEntity
  • 一个RepositoryEntity有一个Repository

以上语句返回了正确的数据,但对象图未正确填充--即,每个Changeset都包含了所有的ChangeEntry,而不仅仅是自己的子项。

以下是这两个类的相关代码片段:

public class Changeset {

    @NotNull
    @OneToMany(mappedBy="changeset", targetEntity=ChangeEntry.class, cascade={CascadeType.ALL }, fetch=FetchType.EAGER )
    private Set<IChangeEntry> changeEntries;

并且...

public class ChangeEntry {

    @NotNull
    @ManyToOne(targetEntity=Changeset.class)
    @ForeignKey(name="FkChangeEntryChangeset")
    private IScmChangeset changeset;

    @NotNull
    @ManyToOne(targetEntity=RepositoryEntity.class, cascade=CascadeType.ALL,fetch=FetchType.EAGER)
    @ForeignKey(name="FkChangeEntryRepoEntity")
    private IRepositoryEntity repositoryEntity;

任何帮助都将不胜感激。
敬礼,
马蒂

你在ChangeEntry中添加了Repository的映射信息,而不是ChangeSet的。 - rudolfson
2个回答

1

Marty:

我曾经遇到过同样的问题,但是找不到合适的解决方案。你可以使用简单的结果转换器来控制返回的对象数量:

CriteriaSpecification.ROOT_ENTITY
CriteriaSpecification.DISTINCT_ROOT_ENTITY

但是对象始终会包含其子对象的完整结果。我偶然发现了一篇优秀的文章,它使用DTO模式以及投影和aliasToBean转换器。

这就是它:http://swik.net/Hibernate/Hibernate+GroupBlog/Hibernate+3.2:+Transformers+for+HQL+and+SQL/cmxs

这对我很有效。最大的问题是你必须创建这些扁平化的DTO对象。对我来说,这不是什么大问题,因为我的专门的DTO对象用于搜索结果并且非常可重用,而且我不需要太多。

我知道这并没有直接解决你的问题,如果你找到实现目标的方法,请更新帖子,因为我很想看到解决方案。


0

通过ID加载一个实体是否正常工作?如果不正常,请继续阅读。:-)

我不确定使用@ForeignKey是否足够。尝试在关系的多侧添加@JoinColumn。例如:

@NotNull
@ManyToOne(targetEntity=RepositoryEntity.class, cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@ForeignKey(name="FkChangeSet")
@JoinColumn(name = "CHANGESET_ID", referencedColumnName = "ID")
private Changeset changeset;

注意:我刚刚看到你正在显示Repository的映射信息,但我认为Changeset的信息看起来很相似。

感谢回复...是的,通过ID加载一个实体确实可以工作。@JoinColumn不应该是必需的,因为Hibernate可以从@ManyToOne的targetEntity中解决这个问题。@ForeignKey注释仅存在于给外键命名,以便在出现问题时(通常会发生!:))我可以获得有意义的错误信息。 - Marty Pitt
关于@ForeignKey - 我猜你已经知道了。关于@JoinColumn - 你不需要给出外键列名吗?引用的列可以从目标实体中解析出来,没错。但是,外键列呢? - rudolfson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接