2016-08-28 40 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部件将在需要时从数据库加载。现在因为没有会话,所以无法从数据库进行懒取。 –

相关问题