【发布时间】:2012-05-22 15:59:38
【问题描述】:
假设在应用程序中您有一个名为 User 的实体。每个用户可以拥有许多使用延迟获取加载的文章。
@Entity
@Table(name = "Users")
public class User {
private Integer id;
private Set<Article> articles = new HashSet<Article>();
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
public Set<Article> getArticles() {...}
}
在 Web 服务端,我想通过 Id 加载用户并将其传递给球衣 Viewable JSP 以返回和显示。我还想为每个请求使用一个会话。
@GET
public Response getUser() {
Session session = getSessionFactory().openSession();
session.beginTransaction();
User user = (User) session.getNamedQuery("getUserById").setInteger("id", 1).uniqueResult();
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("user", user);
Viewable v = new Viewable("/user", dataMap);
Response r = Response.ok(v).build();
session.getTransaction().commit();
session.close();
return r;
}
在 user.jsp 中,我想访问文章并打印出来。
<c:forEach var="a" items="${it.user.articles}">
<span>${a.title}</span>
</c:forEach>
运行此代码并尝试请求 JSP 最终会引发异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: my.package.User.articles, no session or session was closed
发生这种情况是因为显然创建 Viewable、将其传递给 ResponseBuilder 并调用 build() 实际上并没有创建 JSP。在我的方法返回并且会话关闭之后,JSP 会在更远的地方创建。
一个明显的选择是将文章的获取类型设置为渴望,但这并不理想,因为在大多数情况下,当我使用用户对象时,我不需要加载或显示文章。
有没有办法强制 jersey 在我的方法返回之前解释和构造 jsp?是否有某种 onResponse 或 postResponse 侦听器可以传递我的代码以关闭会话?
一般来说,我在处理打开/关闭休眠会话的方式上应该做些什么不同的事情?通过谷歌搜索,每个请求一个会话似乎是大多数人提倡使用的,所以我想我会尝试一下。
【问题讨论】:
标签: java hibernate jsp jersey lazy-loading