Java 按请求执行会话+;使用hibernate和jersey JSP视图进行延迟抓取

Java 按请求执行会话+;使用hibernate和jersey JSP视图进行延迟抓取,java,hibernate,jsp,jersey,lazy-loading,Java,Hibernate,Jsp,Jersey,Lazy Loading,假设在应用程序中有一个名为User的实体。每个用户都可以有许多文章,这些文章是使用延迟抓取加载的 @Entity @Table(name = "Users") public class User { private Integer id; private Set<Article> articles = new HashSet<Article>(); ... @OneToMany(fetch = FetchType.LAZY, mappedBy = "u

假设在应用程序中有一个名为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() {...}
}
这是因为创建可视对象、将其传递给ResponseBuilder并调用build()实际上并没有创建JSP。JSP是在我的方法返回并关闭会话之后,在该行后面的某个地方创建的

一个明显的选择是将文章的获取类型设置为“急切”,但这并不理想,因为在大多数情况下,当我使用用户对象时,我不需要加载或显示文章

有没有办法在我的方法返回之前强制jersey解释和构造jsp?是否有某种onResponse或postResponse侦听器可以通过我的代码关闭会话


在处理打开/关闭hibernate会话的方式上,我是否应该做些不同的事情?通过谷歌搜索,每个请求一个会话似乎是大多数人提倡使用的,所以我想我会尝试一下。

听起来你感兴趣的是,尽管有些人

这种方法确实是解决这个问题的方法

另一种方法是使用EJB或Spring。然后,他们将接管交易处理。EJB在与JPA一起使用时完全透明,Spring为此提供了
org.springframework.orm.JPA.support.OpenEntityManagerInViewFilter
过滤器

如果您的容器支持EJB,那么只需创建一个无状态的:

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public User find(Integer id) {
        return em.createNamedQuery("getUserById", User.class)
            .setParameter("id", id)
            .getSingleResult();
    }

}
并在web服务中使用它,如下所示:

@EJB
private UserService userService;

@GET
public Response getUser() {
    User user = userService.find(1);

    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("user", user);
    Viewable v = new Viewable("/user", dataMap);
    Response r = Response.ok(v).build();
    return r;
}
@EJB
私人用户服务;
@得到
公共响应getUser(){
User=userService.find(1);
Map dataMap=newhashmap();
dataMap.put(“用户”,user);
可视v=新的可视(“/user”,dataMap);
Response r=Response.ok(v.build();
返回r;
}
无需再担心事务和延迟抓取。

您说“在大多数情况下,当我使用用户对象时,我不需要加载或显示文章”,但在这种情况下,您显然确实需要这些数据。这是一个很好的例子,说明了在映射中,获取策略在每个用例中的处理几乎总是比静态的好

例如,这里,您的
getUserById
命名查询可能类似于:

select u from User u where u.id = :id
而是使用以下查询(创建新的命名查询
getUserByIdWithArticles

select u from User u join fetch u.articles where u.id = :id
每个用例所需的数据量几乎总是会因用例而异。获得恰到好处的数据量始终是提高性能的最佳途径

@EJB
private UserService userService;

@GET
public Response getUser() {
    User user = userService.find(1);

    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("user", user);
    Viewable v = new Viewable("/user", dataMap);
    Response r = Response.ok(v).build();
    return r;
}
select u from User u where u.id = :id
select u from User u join fetch u.articles where u.id = :id