1. 程式人生 > >hinbernate懶載入異常org.hibernate.LazyInitializationException: could not initialize proxy

hinbernate懶載入異常org.hibernate.LazyInitializationException: could not initialize proxy

        DataGridJSONModel json = new DataGridJSONModel();       
        PageHolder<IP> holder = ipdao.findPage(page, rows);
        List<IP> list = holder.getList();
        json.setRows(list);
        json.setTotal(holder.getTotal());       
        return json;

在將返回物件json轉換為JSON語句時報錯

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: could not initialize proxy - no Session (through reference chain: com.liyunet.common.json.DataGridJSONModel["rows"]->java.util.ArrayList[0]->com.liyunet.domain.IP["attachments"]->com.liyunet.domain
.IPAttachments_$$_jvst7f7_1c["id"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.liyunet.common.json.DataGridJSONModel["rows"]->java.util.ArrayList[0]->com.liyunet.domain.IP["attachments"]->com.liyunet.domain.IPAttachments_$$_jvst7f7_1c["id"])
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:276) org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) ... ...

可以看出類IP中attachments屬性初始化代理失敗,原因是沒有session(session已關閉)。下面是在實體類IP中的定義程式碼

    @OneToOne(fetch = FetchType.LAZY)//懶載入
    @JoinColumn(name = "attachements_id")
    private IPAttachments attachments;

所以,實際上返回的物件json中rows中物件IP的屬性attachments是個代理,所以要初始化。
有三種方法解決此問題:

1. 遍歷傳遞給rows的list,使用Hinbernate.initialize(attachments);初始化attachments欄位。
list.forEach(ip -> {
    IPAttachments attachments = ip.getAttachments();
    Hibernate.initialize(attachments);
});
2. 使用hql語句立即載入attachments欄位。

修改查詢list的hql語句為:

String hql = "from IP ip inner join fetch ip.attachments order by ip.points desc";
3.使用VO,即將物件IP中需要的幾個欄位查詢出來儲存到一個實體類中,POJO,這樣session關閉之前就會載入,便不會懶載入異常。
class VO{
    private String id;
    ...
}

另外,還有過濾器法,這個還沒有搞懂,暫時擱置。