一尘不染

JPA:请帮助理解“ join fetch”

hibernate

我具有以下实体结构:业务->广告活动->促销,其中一个业务可以有多个广告活动,一个业务可以具有多个促销。一对多关系都声明为LAZY。在我的代码中的一个地方,我需要从业务部门急切地获取两个集合,所以我这样做:

    Query query = entityManager.createQuery("select b from Business b " +
            "left join fetch b.campaigns c " +
            "left join fetch c.promotions where b.id=:id");
query.setParameter("id", b.getId());
business = (Business) query.getResultList().get(0);

但是,查询返回的结果列表中包含4个业务对象,所有4个对象都引用同一个业务实例。在我的数据库中,该公司下有3个广告活动,而这3个广告活动下都有3个广告活动。

我有两个问题:

  1. 首先,我使用List来包含关系的许多方面,但是当程序运行时,我收到“ org.hibernate.HibernateException:无法同时获取多个包”的异常。然后,我用谷歌搜索了这个异常,看起来我必须使用Set而不是List。因此,我将集合更改为Set并开始工作。有人可以告诉我为什么List在这种情况下不起作用吗?

  2. 我期望查询返回单个结果,因为它是针对作为主键的id进行查询,因此应该仅返回单个结果。但事实证明,它在一个List中返回4个实例。这有问题吗?还是这种预期的行为?

任何帮助将不胜感激。


阅读 230

收藏
2020-06-20

共1个答案

一尘不染

生成的sql如下所示:

select * from Business b 
left outer join campaigns c on c.business_id = b.id
left join promotions  p on p.campaign_id = c.id
where b.id=:id

在内部,Hibernate将只有一个业务实例,但是重复项将保留在结果集中。这是预期的行为。可以通过使用DISTINCT子句或通过使用LinkedHashSet来过滤结果来实现所需的行为:

Collection result = new LinkedHashSet(query.getResultList());

只会返回唯一的结果,并保留插入顺序。

每当您尝试以有序的方式(甚至可能重复的项目)急切地获取多个集合时,就会发生“
org.hibernate.HibernateException:无法同时获取多个包”的情况。如果考虑生成的SQL,这确实很有意义。Hibernate无法知道重复的对象是由联接还是由子表中的实际重复数据引起的。看看这个有一个很好的解释。

2020-06-20