关于Hibernate中fatch=eager的bag集合(一个java List)使用Criteria查询出现重复记录的问题...

本文深入分析了在Hibernate框架中,ForumGroup和Forum类的EAGER与LAZY fetch配置对查询结果的差异,特别关注了如何避免查询结果中的重复对象,以及在JPA注解中映射多个集合实体时如何避免同时抓取多个bag集合导致的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于这个问题在JPwH一书的13.2.3一节中做了详细的描述!

例子:ForumGroup和Forum

public class ForumGroup { @OneToMany(fetch=FetchType.EAGER,mappedBy="group") private List<Forum> forums = new ArrayList<Forum>(); } public class Forum { @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="groupId",nullable=false) @org.hibernate.annotations.ForeignKey(name="fk_Forum_groupId_ForumGroup") private ForumGroup group; }

由于ForumGroup的forums被配制为eager fetch,也就是说在加载ForumGroup时,会同一并把它的所有Forum一起加载出来,这个过程是通过left out join来实现的。下面是hibernate打出的sql.

select
this_.id as id3_1_,
this_.creationTime as creation2_3_1_,
this_.description as descript3_3_1_,
this_.modifiedTime as modified4_3_1_,
this_.name as name3_1_,
forums2_.groupId as groupId3_,
forums2_.id as id3_,
forums2_.id as id2_0_,
forums2_.creationTime as creation2_2_0_,
forums2_.description as descript3_2_0_,
forums2_.groupId as groupId2_0_,
forums2_.modifiedTime as modified4_2_0_,
forums2_.name as name2_0_
from
ForumGroup this_
left outer join
Forum forums2_
on this_.id=forums2_.groupId

假定有1个ForumGroup,它有3个Forum,上面的sql会生成3条记录。那么Hibernate是如何封装这3条数据的呢?从实际的代码运行结果中可以看到:首先,Hibernate确实只生成了一个ForumGroup的实例和3个Forum的实例。但是如果你使用loadAllForumGroup时,会返回3个ForumGroup的引用,指向同一个ForumGroup的实例!

如果把ForumGroup的forums被配制为lazy fetch,会解决这个问题。但这也只是回避了这个问题!

正确的解决方法是什么呢?

如果想过滤join和fetch中的重复对象,有两种方法:

1.将续集里封装成set.比如:Set noDupes = new LinkedHashSet(resultList))

2.使用DISTINCT。比如:select distinct i from Item i join fetch i.bids

另外一个问题是:

在用JPA进行注释时,如果一个实体里要映射多个集合实体时,我们不能把两个集合的的FetchType设置为EAGER,此时只能设置为LAZY,否则会报:cannot simultaneously fetch multiple bags。或者我们也可以借助:@IndexColumn (加了它就不再是bag集合了,而是list集合了)。也就是说,hibernate不允许一次抓取多个bag.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值