我具有以下实体结构:业务->广告活动->促销,其中一个业务可以有多个广告活动,一个业务可以具有多个促销。一对多关系都声明为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个广告活动。
我有两个问题:
首先,我使用List来包含关系的许多方面,但是当程序运行时,我收到“ org.hibernate.HibernateException:无法同时获取多个包”的异常。然后,我用谷歌搜索了这个异常,看起来我必须使用Set而不是List。因此,我将集合更改为Set并开始工作。有人可以告诉我为什么List在这种情况下不起作用吗?
我期望查询返回单个结果,因为它是针对作为主键的id进行查询,因此应该仅返回单个结果。但事实证明,它在一个List中返回4个实例。这有问题吗?还是这种预期的行为?
任何帮助将不胜感激。
生成的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无法知道重复的对象是由联接还是由子表中的实际重复数据引起的。看看这个有一个很好的解释。