2016-08-28 39 views
2

我試圖設置一個標籤庫來檢查用戶是否購買了產品。然而,在運行我的標籤庫的時候,我得到這個錯誤:未能延遲初始化一個角色集合:website.User.purchasedProducts,無法初始化代理 - 沒有會話

ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[grailsDispatcherServlet] - Servlet.service() for servlet [grailsDispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.grails.gsp.GroovyPagesException: Error processing GroovyPageView: [views/derbypro/index.gsp:124] Error executing tag <g:ifPurchased>: failed to lazily initialize a collection of role: website.User.purchasedProducts, could not initialize proxy - no Session] with root cause 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: website.User.purchasedProducts, could not initialize proxy - no Session 

這是我的標記庫:

package website 

class PurchasedProductTagLib { 
    def ifPurchased = { attrs, body -> 
     if (!session.user) return 

     if (Product.findById(attrs.product) in session.user.purchasedProducts) { // <-- error here 
      out << body() 
     } 
    } 

    def ifNotPurchased = { attrs, body -> 
     if (!(Product.findById(attrs.product) in session.user?.purchasedProducts)) { 
      out << body() 
     } 
    } 
} 

這裏是我的用戶域類:

package website 

import org.mindrot.jbcrypt.BCrypt 

class User { 
    String username 
    String passwordHash 
    String email 

    static hasMany = [purchasedProducts: Product] 

    User(String username, String password, String email) { 
     this.username = username; 
     passwordHash = BCrypt.hashpw(password, BCrypt.gensalt()) 
     this.email = email 
    } 
} 

這隻似乎在登錄後發生,如果用戶註冊(而且重定向回到此頁面),則不會發生此錯誤。

我有我的標籤庫嵌套在一個另一個,如果這樣做什麼。

回答

3

好吧!由於日誌說No session。您正在使用處於分離狀態的對象。因此,要麼將對象附加回來,要麼通過id來獲取對象。

if(!session.user.isAttached()){ 
    session.user.attach(); 
} 

或者

Long id = session.user.id.toLong(); 
User user = User.get(id); 

無論您將對象附加到會話的方式。

編輯

另一個解決方案可以是熱切負載的hasMany一部分。但我不喜歡這個解決方案,因爲它會減慢我的域取指。此外,它會獲取可能不需要在所有地方的許多數據。

+0

它爲什麼會進入這種分離狀態? –

+1

那麼可能有幾個原因。據我所知,當我們嘗試做與DB有關的任何操作時,我們打開一個會話並關閉它。這裏,您獲取的對象來自HttpSession,它具有關聯的Lazy獲取類型。這意味着hasMany部件將在需要時從數據庫加載。現在因爲沒有會話,所以無法從數據庫進行懶取。 –

相關問題