JPA:请帮助理解“加入抓取” [英] JPA: please help understanding "join fetch"

查看:96
本文介绍了JPA:请帮助理解“加入抓取”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 查询查询= entityManager。 createQuery(从业务b中选择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个Business对象,所有4个对象都被引用到同一业务实例。在我的数据库中,该业务下有3个广告系列,所有3个广告系列都有3个广告系列。



我有两个问题:


  1. 首先,我使用List来包含关系的许多方面,但是当程序运行时,我会得到org.hibernate.HibernateException:不能同时获取多个包的例外。然后我GOOGLE了这个异常,它看起来像我必须使用Set,而不是List。所以我把集合改为Set,它工作。有人能告诉我为什么List在这种情况下不起作用吗?

  2. 我期望查询返回单个结果,因为它查询的是id,这是主键,因此应该只返回单个结果。但事实证明,它返回列表中的4个实例。这是一个问题吗?或者这是预期的行为? 解决方案

生成的sql看起来像这样:

  select * from Business b 
在c.business_id = b.id
上留下加入促销p在p.campaign_id = c.id
其中b.id =:id

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

 收集结果=新的LinkedHashSet(query.getResultList()); 

这将只返回唯一的结果,保留广告订单。



每当您尝试以有序方式(可能重复项目)急于获取多个集合时,都会发生org.hibernate.HibernateException:无法同时获取多个行李。如果考虑生成的SQL,这确实有意义。 Hibernate无法知道重复的对象是由连接还是由子表中的实际重复数据引起的。查看这个可以得到很好的解释。


I have the following entity structure: Business --> Campaign --> Promotion, where ONE Business can have MANY Campaigns and ONE Campaign can have MANY Promotions. Both one-to-many relations are declared as LAZY. One place in my code, I need to eagerly fetch both collections from a Business, so I do:

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

However, the query returns a result list that contains 4 Business objects in it, all 4 objects are referring to the same Business instance. In my database, this business has 3 campaigns under it, and all the 3 campaigns have 3 promotions under them.

I have two questions:

  1. At first, I use List to contains the many sides of the relations, but when program runs, I get "org.hibernate.HibernateException: cannot simultaneously fetch multiple bags" exception. Then I googled this exception and it looks like I have to use Set, instead of List. So I changed the collection to Set and it worked. Can someone tell me why List won't work in this situation?

  2. I am expecting the query to return a single result, because it's querying against the id, which is the primary key and thus should only return a single result. But it turns out that it returns 4 instances in a List. Is this a problem? Or is this expected behavior?

Any help will be greatly appreciated.

解决方案

The generated sql would look something like:

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

Internally Hibernate will have only one Business instance, however the duplicates will be preserved in the result set. This is expected behaviour. The behaviour you require can be acheived either by using the DISTINCT clause, or by using a LinkedHashSet to filter results:

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

which will return only unique results, preserving insertion order.

The "org.hibernate.HibernateException: cannot simultaneously fetch multiple bags" happens whenever you try to eagerly fetch more than one collection in an ordered fashion (and possibly duplicated items). This does sort of make sense if you consider the generated SQL. Hibernate has no way of knowing whether a duplicated object was caused by the join or by actual duplicate data in the child table. Look at this for a good explanation.

这篇关于JPA:请帮助理解“加入抓取”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆