【问题标题】:The dreaded Lazy Initialization Exception when using JAX-WS and JEE6使用 JAX-WS 和 JEE6 时的可怕延迟初始化异常
【发布时间】:2011-01-22 13:07:24
【问题描述】:

在使用 JAX-WS @Path 和 @Stateless(或 @RequestScoped)注释时,我得到了一个 LIE。代码:

@Path("/users")
@Stateless
@Produces(MediaType.APPLICATION_XML)
public class UserResourceRESTService {
  @Inject
  @UserRepository
  @PersistenceContext
  private EntityManager em;

  @GET
  @Path("/{id:[1-9][0-9]*}")
  public User lookupUserById(@PathParam("id") long id) {
      return em.find(User.class, id);
  }
}

我得到的实际异常:

org.hibernate.LazyInitializationException: 无法初始化代理 - 没有会话

用户对象有一个地址,它有一个国家。如果我将其更改为有状态 bean 并使用扩展上下文它可以工作,但这真的不应该是 SFSB 吗?我有点茫然,为什么“em”在使用无状态 bean 时无法打开会话?

【问题讨论】:

  • 在 NullPointerException 之后,这是 java 世界中最常见的异常。您在 google 和 stackoverflow 上的搜索告诉了您什么?

标签: java hibernate transactions lazy-loading java-ee-6


【解决方案1】:

当您在扩展持久性上下文中操作时,您返回的用户实体仍处于托管状态,并且当您使用事务持久性上下文时,一旦 lookupUserById() 方法返回并且该方法的结果是一个已经与持久性上下文分离的实体,事务就会结束.结果,该实体的所有标记为 LAZY 的属性都不再可访问。

如果您想在实体与持久性上下文分离后访问这些惰性属性,请在从 lookupUserById 方法返回之前调用该实体上的特定 getter 方法。

即

 public User lookupUserById(@PathParam("id") long id) {
  User user =  em.find(User.class, id);
  user.getAddress().getCountry();
  return user;
}

【讨论】:

  • 我明白了,谢谢。我猜该方法返回 User 对象,然后 XML 序列化通过 @Produces 标记发生 - 因此是 LIE。我仍然有点惊讶,因为从单一方法以 RESTful 方式将 GET 请求序列化为 XML/JSon 是很常见的。
【解决方案2】:

您还可以使用fetch = FetchType.EAGER 在 User 类中注释您的关系。如果您总是返回所有内容,那么我认为延迟加载是没有意义的。

【讨论】:

  • 谢谢,在这种情况下,我实际上采用了这种方法(使用 FetchType.EAGER)。我真的很好奇,因为这似乎是 RESTful 服务的常见问题。
  • 当然这是一个错误,会话不应该在 SLSB 中保持打开状态,直到 @Producer 完成生产...???
猜你喜欢
  • 2012-07-27
  • 2011-08-21
  • 2014-03-21
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多