org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包 [英] org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags

查看:24
本文介绍了org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我的代码这里我使用多个列表从数据库中获取数据.从 hql 查询中获取数据时显示异常.

Pojo 类

公共类 BillDetails 实现了 java.io.Serializable {私人长帐单号;//其他字段@LazyCollection(LazyCollectionOption.FALSE)私人列表<BillPaidDetails>billPaidDetailses = new ArrayList();私有集 productReplacements = 新 HashSet(0);@LazyCollection(LazyCollectionOption.FALSE)私人列表<BillProduct>billProductList = new ArrayList();//getter 和 setter}

hmb.xml 文件

<id name="billNo" type="java.lang.Long"><列名="bill_no"/><generator class="identity"/></id><bag name="billProductList" table="bill_product" inverse="true" lazy="false" fetch="join"><键><column name="bill_no" not-null="true"/></key><一对多类=iland.hbm.BillProduct"/></包><bag name="billPaidDetailses" table="bill_paid_details" inverse="true" lazy="false" fetch="select"><键><column name="bill_no" not-null="true"/></key><一对多类=iland.hbm.BillPaidDetails"/></包><set name="productReplacements" table="product_replacement" inverse="true" lazy="false" fetch="join"><键><column name="bill_no" not-null="true"/></key><一对多类="iland.hbm.ProductReplacement"/></set></class>

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 作为 bpd "+ "left join fetch bpd.product as pd "+"left join fetch bd.billPaidDetailses 作为 bpds"+ "其中 bd.billNo=:id "+ "和 bd.client.id=:cid ";

我正在尝试按照查询从数据库中获取数据,但这显示org.hibernate.loader.MultipleBagFetchException: 不能同时获取多个包如何解决这个问题

解决方案

Hibernate 不允许获取多个包,因为那样会生成一个 笛卡尔积.

现在,您会发现很多答案、博客文章、视频或其他资源都告诉您对收藏使用Set 而不是List.>

这个建议太糟糕了!

使用 Sets 而不是 Lists 将使 MultipleBagFetchException 消失,但笛卡尔积仍然存在.

正确的修复

而不是在单个 JPQL 或 Criteria API 查询中使用多个 JOIN FETCH:

Listpost = entityManager.createQuery(""";选择 p来自邮政左连接获取 p.comments左连接获取 p.tags其中 :minId 和 :maxId 之间的 p.id""", Post.class).setParameter(minId", 1L).setParameter("maxId", 50L).getResultList();

您可以执行以下操作:

Listpost = entityManager.createQuery(""";选择不同的 p来自邮政左连接获取 p.comments其中 :minId 和 :maxId 之间的 p.id""", Post.class).setParameter(minId", 1L).setParameter("maxId", 50L).setHint(QueryHints.PASS_DISTINCT_THROUGH,假).getResultList();post = entityManager.createQuery(""";选择不同的 p来自邮政左连接获取 p.tags t其中 p 在 :posts""", Post.class).setParameter(帖子", 帖子).setHint(QueryHints.PASS_DISTINCT_THROUGH,假).getResultList();

只要您使用 JOIN FETCH 最多获取一个集合,就可以了.通过使用多个查询,您将避免使用笛卡尔积,因为除了第一个集合之外的任何其他集合都是使用辅助查询获取的.

Following is my code Here I am using multiple lists to fetch data from database. On fetching data from hql query it is showing exception.

Pojo Class

public class BillDetails implements java.io.Serializable {

private Long billNo;
// other fields
@LazyCollection(LazyCollectionOption.FALSE)
private List<BillPaidDetails> billPaidDetailses = new ArrayList<BillPaidDetails>();
private Set productReplacements = new HashSet(0);
@LazyCollection(LazyCollectionOption.FALSE)
private List<BillProduct> billProductList = new ArrayList<BillProduct>();
//getter and setter
}

hmb.xml file

<class name="iland.hbm.BillDetails" table="bill_details" catalog="retail_shop">
        <id name="billNo" type="java.lang.Long">
            <column name="bill_no" />
            <generator class="identity" />
        </id>
 <bag name="billProductList" table="bill_product" inverse="true" lazy="false" fetch="join">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.BillProduct" />
        </bag>
        <bag name="billPaidDetailses" table="bill_paid_details" inverse="true" lazy="false" fetch="select">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.BillPaidDetails" />
        </bag>
        <set name="productReplacements" table="product_replacement" inverse="true" lazy="false" fetch="join">
            <key>
                <column name="bill_no" not-null="true" />
            </key>
            <one-to-many class="iland.hbm.ProductReplacement" />
        </set>
    </class>

Hql query

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

I am trying following query to fetch data from database but this is showing org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags How to resolve this

解决方案

Hibernate doesn't allow fetching more than one bag because that would generate a Cartesian product.

Now, you will find lots of answers, blog posts, videos, or other resources telling you to use a Set instead of a List for your collections.

That's terrible advice!

Using Sets instead of Lists will make the MultipleBagFetchException go away, but the Cartesian Product will still be there.

The right fix

Instead of using multiple JOIN FETCH in a single JPQL or Criteria API query:

List<Post> posts = entityManager.createQuery("""
    select p
    from Post p
    left join fetch p.comments
    left join fetch p.tags
    where p.id between :minId and :maxId
    """, Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.getResultList();

You can do the following trick:

List<Post> posts = entityManager.createQuery("""
    select distinct p
    from Post p
    left join fetch p.comments
    where p.id between :minId and :maxId
    """, Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

posts = entityManager.createQuery("""
    select distinct p
    from Post p
    left join fetch p.tags t
    where p in :posts
    """, Post.class)
.setParameter("posts", posts)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

As long as you fetch at most one collection using JOIN FETCH, you will be fine. By using multiple queries, you will avoid the Cartesian Product since any other collection but the first one is fetched using a secondary query.

这篇关于org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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