org.hibernate.loader.MultipleBagFetchException:无法同时获取多个行李

以下是我的代码在这里,我使用多个列表从数据库中获取数据。 从hql查询中获取数据时,它显示exception。

Pojo类

public class BillDetails implements java.io.Serializable { private Long billNo; // other fields @LazyCollection(LazyCollectionOption.FALSE) private List billPaidDetailses = new ArrayList(); private Set productReplacements = new HashSet(0); @LazyCollection(LazyCollectionOption.FALSE) private List billProductList = new ArrayList(); //getter and setter } 

hmb.xml文件

                         

Hql查询

 String hql = "select distinct bd,sum(bpds.amount) from BillDetails as bd " + "left join fetch bd.customerDetails as cd " + "left join fetch bd.billProductList as bpd " + "left join fetch bpd.product as pd " +"left join fetch bd.billPaidDetailses as bpds " + "where bd.billNo=:id " + "and bd.client.id=:cid "; 

我正在尝试跟随查询从数据库中获取数据,但这显示org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags如何解决此问题

正如本文所述 ,Hibernate不允许获取多个包,因为这会生成笛卡尔积 。

您可以将行李更改为集合,并添加order-by="id"属性以“模拟”有序列表行为:

 private Set billPaidDetailses = new LinkedHashSet<>(); private Set billProductList = new LinkedHashSet<>();             

但只是因为你可以,这并不意味着你应该。

您可以做的是在原始SQL查询中获取最多一个集合,而之后使用辅助查询获取其他集合。 这样你就可以避免笛卡尔积。

另一种选择是使用从子实体到父实体的多级提取 。

对我来说,我有同样的错误,我通过添加hibernate @Fetch的注释解决了

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) @Fetch(value = FetchMode.SUBSELECT) private List childs; 

您只能为实体( billPaidDetailsesbillProductList )的一个关系加入billProductList

考虑在需要时使用惰性关联和加载集合,或者使用惰性关联并使用Hibernate.initialize(..)手动加载集合。 至少那是我遇到类似问题时得出的结论。

无论哪种方式,它都会对数据库进行多次查询。

更改为Set是最佳解决方案。 但是,如果你不能用List替换List (就像我的情况那样,大量使用特定于Lists的JSF标签),如果你可以使用Hibernate专有注释,你可以指定@IndexColumn (name = "INDEX_COL") 。 该解决方案对我来说效果更好,更改为Set将需要大量的重构。

所以,你的代码将是这样的:

 @IndexColumn (name = "INDEX_COL") private List billPaidDetailses = new ArrayList(); @IndexColumn (name = "INDEX_COL") private List billProductList = new ArrayList(); 

正如Igor在评论中建议的那样,您还可以创建代理方法来返回列表。 我没有尝试过,但如果你不能使用Hibernate专有注释,那将是一个很好的选择。

您的请求获取的数据太多而HIbernate无法加载所有数据。 减少您的请求和/或配置您的实体以检索所需的数据