使用JAX-WS和JEE6时可怕的Lazy Initialization Exception

时间:2011-01-22 13:07:24

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

使用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时无法打开会话,我有点不知所措?

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

您还可以使用fetch = FetchType.EAGER在User类中注释您的关系。如果你总是归还所有东西,那么在我看来,没有必要进行延迟加载。