MultipleBagFetchException: cannot simultaneously fetch multiple bags
Posted on: 2013-11-20, Last modified: 2015-07-31, View: 3111

使用Hibernate3.2的时候遇到这样的异常:

javax.persistence.PersistenceException: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags
     at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:217)
     at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:114)
        ........

这个异常被org.hibernate.loader.BasicLoader抛出,它意思是hibernate不能在同一时间取出两个或者更多bags(例如:List,Collection对象)

问题原因

如果一个实体有多余一个的non-lazy关联将被视为一个bag(e.g., java.util.List or java.util.Collection properties annotated with @org.hibernate.annotations.CollectionOfElements or @OneToMany or @ManyToMany and not annotated with @org.hibernate.annotations.IndexColumn), Hibernate将会获取实体失败。

假设我们有个Parent类和两个child类,child1和child2, parent对每一个child类型有一个bag,如以下代码定义:

@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
List<Child1> child1s = new LinkedList<Child1>();
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
List<Child2> child2s= new LinkedList<Child2>();

我们在每个关联上面定义了bag和EAGER, Hibernate会生成如下的sql语句:

select 
   parent0_.id as p_id, parent0_.name as p_name, child1s1_.parent_id as c1_p_id,
   child1s1_.id as c1_id, child1s1_.id as c1_id_1, child1s1_.parent_id as 
   c1_p_id_1, child1s1_.value as c1_val,child2s2_.parent_id as c2_p_id,
   child2s2_.id as c2_id, child2s2_.id as c2_id_, 
   child2s2_.parent_id as c2_p_id_1, child2s2_.value as c2_val 
from 
   PARENT parent0_ left outer join 
           CHILD1 child1s1_ on parent0_.id=child1s1_.parent_id left outer join 
           CHILD2 child2s2_ on parent0_.id=child2s2_.parent_id 
where 
   parent0_.id=?

现在假设数据库表结构如下:

PARENT table
---------------------------
ID      NAME

122      PARENT-1


CHILD1 table
------------------------------
ID      VALUE               PARENT_ID

123       CHILD1-1       122
1       CHILD1-2        122


CHILD2 table
------------------------------
ID      VALUE              PARENT_ID

124      CHILD2-1      122

加入我们输入的id=122, 查询完成以后会输出这样的结果:

P_ID    P_NAME    C1_P_ID    C1_ID    C1_ID_1    C1_P_ID_1    C1_VAL         C2_P_ID      C2_ID   C2_ID_     C2_P_ID_1    C2_VAL

122            Parent-1            122                    123            123                    122                    CHILD1-1    122              124     124    122                    CHILD2-1

122            Parent-1       122                     1            1                     122            CHILD1-2     122              124     124    122                    CHILD2-1

解决方案

针对这个问题现在有三个解决方案:

1. 使用LAZY loading获得关联实体,不用把所有的关联关系都改成lazy, 只要保证在同一个实体上面没有多于一个的EAGER关联就可以。

2. 在关联关系上使用@IndexColumn标签:

@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@IndexColumn(name="INDEX_COL")
List<Child1> child1s = new LinkedList<Child1>();

使用@IndexColumn可以使Hibernate在获取父对象时同时也获取关联对象的index, Hibernate可以借助index判断当前对象时候已经被加载过。

3. 第三个方法是使用java.util.Set 替代java.util.List和java.util.Collection。

 

From: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html
Go
Friend Links:
Sonft