2017-07-14 128 views
0

我已经用hibernate和狂野地构建了一个Java EE应用程序10.我没有使用任何servlet,而是使用Java API为RESTful WebService构建的REST API。因为我的模特变得越来越大,我将我的收藏从FetchType.EAGER设置为FetchType.LAZY。现在我得到一个LazyInitializationException与消息could not initialize proxy - no Session。我想我明白为什么会发生这种情况,但我不明白hibernate何时试图访问代理服务器。Hibernate在3层java ee应用程序中延迟加载

实体:

@Entity 
public class User implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Version 
    private Timestamp lastChanged; 

    @NotNull 
    private Date creationDate; 

    @ManyToMany 
    private Set<Entity> lazyEntity; 

    public User() { } 

    // getters and setters 
} 

DAO:

public interface UserDAO { 
    public List<User> getAll(); 
} 

豆:

@Stateless 
@Remote(UserDAO.class) 
public class UserBean<User> implements UserDAO { 

    @PersistenceContext 
    protected EntityManager em; 

    @Override 
    public List<User> getAll() { 
     return this.em.createQuery("SELECT u FROM User u ORDER BY u.creationDate", User.class) 
         .getResultList(); 
    } 
} 

ENDP oint:

@Path("/users") 
@Stateless 
public class UsersEndpoint { 

    @EJB 
    private UserDAO userDAO; 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getAll() { 
     List<User> users = userDAO.getAll(); 
     if (users.size() == 0) 
      return Response.status(Response.Status.NOT_FOUND) 
          .build(); 
     return Response.ok(users).build(); 
    } 
} 

我的问题是,为什么没有在lazyEntity只是返回空但抛出一个错误?在哪个部分是hibernate尝试访问lazyEntity,因为正如你在上面的代码中看到的,我不会尝试在API端点内访问。我能赶上例外吗?

我能做些什么来接收下面的对象而不会发生异常?我已经看到,我可以通过更改属性hibernate.enable_lazy_load_no_trans来禁用它。但我也read,这是不强烈推荐。

User { 
    id: 1, 
    lastChanged: 0981283812738, 
    creationDate: 2178371283098, 
    lazyEntity: null 
} 

回答

1

我认为这个问题是在序列化到GETALL()方法的结果JSON在UsersEndpoint(通过该方法的注释触发)。

我假设你使用Jersey + Jackson(这是一种常见的Java < - > JSON转换器)。

当getAll()方法完成时,Jackson将获取该方法的结果并通过获取User类的所有数据尝试将其转换为JSON。要做到这一点,Jackson在User类中调用getLazyEntity()方法,并且在延迟加载时触发数据库访问(并因会话关闭而失败)。

如果您希望在JSON响应中拥有“lazyEntity”数据,则必须在会话关闭之前获取数据:在HQL查询中使用fetch连接的DAO内部。

如果你不想在JSON中使用lazyEntity,那么你必须告诉Jackson不要序列化lazyEntity,你可以用Jackson视图来做到这一点。请参阅How can a @JsonView working with jerseyhttp://wiki.fasterxml.com/JacksonJsonViews

+0

谢谢你的解释。但我无法找到'@ JsonView'注释。有另一种方法吗? – user289520

+0

好的,我明白了。但不是'@ JsonView',我使用了@ @ JsonIgnore'。我认为这是更少的代码,或者你不同意? – user289520

+0

我同意'@ JsonView'很麻烦。它的优点是可以将一个属性映射到多个'@ JsonView',它允许一些端点序列化对象的所有属性,以及其他端点只序列化对象的一部分。 – PCO