为什么Hibernate不允许同时抓取两个和两个以上的平行bag集合
为什么Hibernate不允许同时抓取两个和两个以上的平行bag集合
猪刚烈 发表于3年前
为什么Hibernate不允许同时抓取两个和两个以上的平行bag集合
  • 发表于 3年前
  • 阅读 8
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 学生专属云服务套餐 10元起购>>>   

在hibernate中, 如果试图同时抓取两个或两个以上平行的bag集合,会抛出这个异常:org.hibernate.HibernateException: cannot simultaneously fetch multiple bags。对于这种情况,Hibernate文档给出的解释是: The resultset of a product can’t be converted into bag collections, because Hibernate can’t know which rows contain duplicates that are valid (bags allow duplicates) and which aren’t.

这里具体再解释一下。我们知道:抓取平行集合会产生笛卡尔积, 是笛卡尔积就会有重复记录。这对于允许有重复记录的bag集合有麻烦了,因为hibernate无法区分(确实地说是bag集合无法区分)这些重复的记录是因笛卡尔积而产生的(如果是这种记录,在封装对象是就要排除出去)还是真正的记录。注意:Hibernate不会通过比较ID来确定它们是否重复的,因为集合内的元素不一定都有ID的,比如值对象。 这也正是idbag为什么不存在这个问题的原因所在!在这种情况下,如果hibernate不抛出异常,就只能向bag集合中添加这些元素,而bag集合是允许重复记录的,这样,bag集合就会照单全收。对于set集合就不会出现这种情况,因为在添加对象时,它会检查是否已经加过这个元素了,重复的元素就会被排除出去。从这里我们也应该注意到:对于Set集合内的元素,重写hashCode和equals方法是多么地重要!

举个例子吧:对象A有一个B的bag集合和一个C的bag集合。假定a1有一个b1和b2组成的B集合,和一个c1组成的C集合,那么当使用join平行抓取B和C集合时,生成的结果集是:

a1,b1,c1

a1,b2,c1

现在,当hibernate将这个结果集封装成a1对象时,对于a1的C集合,hibernate首先将第一条记录中的c1加到集合里,当遇到第二条记录的c1时,因为C集体是一个bag集合,它不做检查就会接受这个c1.这就是问题的所在。即使这两个c1所有值全都是一样的,也包括ID,但是将之封装为对象加入C集合时,它是不做检查的。如果是set集合,它会检查它们的hashCode和equals方法,通过比较主键或业务主键,来确定它们是不是重复的。

共有 人打赏支持
粉丝 21
博文 708
码字总数 110
作品 1
×
猪刚烈
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: