2017-07-14 126 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