2012-11-25 39 views
3

我越來越瘋狂,我使用Spring MVC的3.1.2和傑克遜2Spring MVC的3.1.2 +傑克遜2:LazyInitializationException中時懶洋洋地初始化集合 - 沒有會話或會話關閉

有錯誤

我有以下的模型類:

@Entity 
@Table(name = "USER") 
@JsonIgnoreProperties(ignoreUnknown=true) 
public class User implements Serializable 
{ 
    @Id 
    @SequenceGenerator(name = "USER_ID", sequenceName = "USER_ID_SEQ", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID") 
    private Long id; 

    @Column(length = 50, nullable = false) 
    private String firstName; 

    @Column(length = 50, nullable = false) 
    private String lastName; 

    @ManyToMany 
    @JoinTable(name = "FRIENDS", 
     joinColumns = @JoinColumn(name = "personId"), 
     inverseJoinColumns = @JoinColumn(name = "friendId") 
    ) 
    @JsonManagedReference 
    private List<User> friends; 

    @ManyToMany 
    @JoinTable(name="FRIENDS", 
     [email protected](name="friendId"), 
     [email protected](name="personId") 
    ) 
    @JsonIgnore 
    private List<User> friendOf; 

    // Other attributes and methods... 
} 

當我到達用戶的單個實例是正確傑克遜序列化。但是,當我試圖讓用戶包含的朋友的一個實例,下面的異常被拋出:

org.hibernate.LazyInitializationException:無法初始化懶洋洋作用 的集合:com.frooid.model.User .friends,沒有會話或 會話關閉

我使用一個單一的HQL得到這個實例:

select u from User u left join fetch u.friends f where u.id = :id 

感謝大家!

+0

你能發佈試圖訪問集合的代碼嗎?它是否訪問jsp或控制器中的集合? –

+0

我正在使用Spring MVC訪問它,通過控制器訪問服務,然後在DAO中訪問它。 Controller使用getJSON方法通過JQuery訪問。 –

+0

也許一個愚蠢的問題,但你的服務標記@Transactional?你可以發佈你的服務方法嗎? –

回答

5

嘗試使用OpenSessionInViewFilter,而這是爲了訪問視圖中的延遲初始化字段,它可以保持會話打開,以使Jackson能夠訪問該集合。

OpenSessionInViewFilter將Hibernate Session綁定到線程,以完成請求的整個處理。用於「在視圖中打開會話」模式,即允許在Web視圖中進行延遲加載,儘管原始事務已經完成。

在web.xml

<filter> 
    <filter-name>OpenSessionInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>OpenSessionInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

API Documentation

+0

Hi @ kmb385!你的解決方案非常棒!但是,由於模型中的自我關係,拋出了一個Stackoverflow異常。你知道是否有某種方法可以限制傑克遜可以導航的級別,直到停止序列化它爲止? –

+0

http://stackoverflow.com/questions/10065002/jackson-serialization-of-entities-with-birectional-relationships-avoiding-cyc –

+0

當我試圖使用這些過濾器時,我得到:'沒有符合條件的bean [ javax.persistence.EntityManagerFactory]被定義'。我需要提一下,我一般使用Hibernate(而不是持久性)嗎? – miho

5

一對多關聯是延遲加載默認情況下。這意味着只有在調用friends列表的方法時纔會從數據庫加載用戶的朋友。

此延遲加載只能在用於加載用戶的會話打開時發生。因此,如果您在沒有加載好友列表的情況下從交易方法中返回用戶,會話將被關閉,並嘗試加載freinds列表將導致您遇到的異常。

因此,如果客戶端需要加載freinds列表,則可以使用HQL獲取朋友,或者通過調用列表中的方法或致電Hibernate.initialize(user.getFriends()),在服務方法內強制列表的初始化。

編輯:既然你有你的HQL的提取,它應該工作。另一個問題是雙向關聯被映射兩次:一次在friends字段中,一次在friendOf字段中。其中一個關聯必須使用mappedBy屬性標記爲另一個的相反值:

@ManyToMany(mappedBy = "friends") 
@JsonIgnore 
private List<User> friendOf; 
+0

不幸的是,這個解決方案沒有奏效。例外仍在發生...... :( –

+0

好吧,現在我想起它,這個問題可能來自於你有一個遞歸關聯的事實:用戶有擁有朋友,有朋友等的朋友。用戶的序列化一定是可以的,但是傑克遜可能會嘗試序列化朋友和他們的朋友等等。你需要在某個地方削減流程。 –

+0

噢,我的上帝@ jb-nizet ...你有一些想法,我該如何解決它?如果你有一些建議,包括模型的變化,我會非常感謝!:) –

0

我有過類似的問題。方法是創建一個新的類(視圖),並在每個屬性的@JsonView({NewClass1.class,NewClass2.class})中添加此類,在您的屬性定義的實體中。您可以選擇想要作爲響應的一部分加載的變量,並將該類包含在@JsonView中。就這麼簡單!

相關問題