直截了当。我获得了Hibernate异常Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
。
我有Parent --(1-*)--> Child --(1-*)--> Grandchild
单向关系中的3个实体:
NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters
在这两种关系中我都定义了FetchType.LAZY
。
@Entity
@Table(name = "NETWORK_ELEMENTS")
public class NetworkElement extends Device {
@Id
@Column(name = "ID_DEVICE")
private Long id;
@ManyToOne(targetEntity = DeviceLocation.class, fetch = FetchType.LAZY)
@JoinColumn(name = "ID_DEVICE_LOCATION")
private DeviceLocation deviceLocation;
@Column(name = "MODEL", length = 30)
private String model;
@Column(name = "TYPE", length = 30)
private String type;
@Column(name = "IMAGE", length = 50)
private String image;
@OneToMany(orphanRemoval = true, fetch = FetchType.LAZY, targetEntity = NetworkElementInterface.class, cascade=CascadeType.ALL)
@Size(min = 0, max = 99)
private List<NetworkElementInterface> interfaces;
}
@Entity
@Table(name = "NETWORK_ELEMENT_INTERFACES")
public class NetworkElementInterface {
@Id
@Column(name = "ID_NETWORK_ELEMENT_INTERFACES")
protected Long id;
@Column(name = "NAME")
private String name;
@Column(name = "SPEED")
private Long speed;
@Column(name = "DUPLEX")
private String duplex;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "NETWORK_ELEMENT_INTERFACE_COUNTERS", joinColumns = @JoinColumn(name = "ID_NETWORK_ELEMENT_INTERFACE"))
@Type(type = "com.netsuite.wind.entity.NetworkElementInterfaceCounters")
private List<NetworkElementInterfaceCounters> interfaceCountersHistory;
}
@Embeddable
public class NetworkElementInterfaceCounters {
private Long inputErrors;
private Long inputDrops;
private Long inputDiscards;
private Long inputCRCErrors;
private Long inputFifoErrors;
private Long outputErros;
private Long outputDrops;
private Long outputCRCErrors;
private Long outputFifoErrors;
}
我想要实现的目标是:
在我的DAO中 1)
创建一个方法,该方法将Parent
完全填充children
和grandchildren
。 (NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters)
。
1b) (not really important here, just curious)
最后,我还希望在我的children
NetworkElement
对象中填充其他类型的DeviceLocation
以及填充的NetworkInterfaces
。
我的NetworkElement
的DAO方法:
@Transactional()
@SuppressWarnings("unchecked")
public NetworkElement getByIdWithInterfaces(Long id) {
final Session session = sessionFactory.getCurrentSession();
------------------------------------------------------
// This works well when I only want children to by populated
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces WHERE ne.id = :id");
------------------------------------------------------
// This doesn't work when I also try to fetch grandchildren. I am given Hibernate exception: "cannot simultaneously fetch multiple bags"
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
------------------------------------------------------
// Eventually I tried "FETCH ALL PROPERTIES" which also doesn't work.
Query query = session.createQuery("FROM NetworkElement ne FETCH ALL PROPERTIES WHERE ne.id = :id");
------------------------------------------------------
query.setParameter("id", id);
NetworkElement result = null;
try {
result = (NetworkElement) query.uniqueResult();
} catch (NoResultException e) {
e.printStackTrace();
}
return result;
}
所以:
1)
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
尽量让它发挥作用。
我认为我遗漏了一些注释,以避免这种异常。我注意到在一些例子中他们使用的是@IndexColumn
,但是这个注释已被弃用。请注意这方面的任何说明。