【发布时间】:2017-01-17 14:22:21
【问题描述】:
我在我的应用程序中遇到了 JPA 的这个问题。我有一个父实体 Artist 与其他实体一对一/多蚀刻关系,我都设置为延迟获取。我使用连接查询来获取这些实体。这一切似乎都很好,但有时我会得到一个 LazyInitializationException。我在后端使用带有 JPA 的无状态 EJB,在 Web 层使用 Spring MVC。方法如下:
public Artist getArtistWithChildren(long id, boolean isFetchReviews, boolean isFetchRequests, boolean isFetchGigs, boolean isFetchVenues) {
StringBuilder sql = new StringBuilder();
sql.append("select a from Artist a join fetch a.members mrs");
if(isFetchReviews) {
sql.append(" left join a.reviews rvs");
} if(isFetchRequests) {
sql.append(" left join a.requests rqs");
} if(isFetchGigs) {
sql.append(" left join a.gigs gs");
} if(isFetchVenues) {
sql.append(" left join a.venues vs");
}
sql.append(" where a.id=:id");
TypedQuery<Artist> query = em.createQuery(sql.toString(), Artist.class);
query.setParameter("id", id);
query.setMaxResults(1);
List<Artist> resultList = query.getResultList();
return resultList.get(0);
}
这里是实体类 Artist
@Entity
@Table(name="ARTIST")
public class Artist extends DescribingEntity {
private static final long serialVersionUID = -7264327449601568983L;
@ManyToMany(mappedBy="artists", targetEntity=Member.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH})
private List<Member> members;
@OneToMany(mappedBy="artist", targetEntity=VenueReview.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE})
private List<VenueReview> reviews;
@OneToMany(mappedBy="artist", targetEntity=Gig.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE})
private List<Gig> gigs;
@OneToMany(mappedBy="artist", targetEntity=GigRequest.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE})
private List<GigRequest> requests;
@ManyToMany(cascade={MERGE, REFRESH}, fetch=FetchType.LAZY)
@JoinTable(name="VENUE_ARTIST_REL",
joinColumns=@JoinColumn(name="ARTIST_ID", referencedColumnName="ARTIST_ID"),
inverseJoinColumns=@JoinColumn(name="VENUE_ID", referencedColumnName="VENUE_ID"))
private List<Venue> venues;
getters and setters...
然后我进入调试模式以找出问题所在,并且当我逐步执行该方法时,它不会返回错误并且不会引发异常。会不会是集合返回得太快,以至于数据库中的所有数据都没有时间正确填充?我是 JPA 的新手,所以请让我知道我做错了什么。这是一个例子。我在这里使用左连接,因为我不需要得到结果,但我确实需要一个实例化的集合。
我已经使用 Arquillian 测试过同样的事情并且没有错误,对于场景相同的其他实体,我也有类似的方法,只是运行它会导致错误,而逐步调试则不会。
在子集合上使用 Hibernate.initialize(Object o) 效果很好,但据我所知,这不是一件好事,因为我必须为每个孩子进行数据库查询(如果我错了,请纠正我)。
我在堆栈跟踪中添加了一个 pastebin 链接
【问题讨论】:
标签: hibernate spring-mvc ejb jpa-2.0 lazy-initialization