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;
您只能为实体( billPaidDetailses
或billProductList
)的一个关系加入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无法加载所有数据。 减少您的请求和/或配置您的实体以检索所需的数据