代码之家  ›  专栏  ›  技术社区  ›  Chris Smith

未能延迟初始化角色集合:website.User。purchasedProducts,无法初始化代理-无会话

  •  2
  • Chris Smith  · 技术社区  · 8 年前

    我正在尝试设置一个标记库来检查用户是否购买了产品。然而,当我的taglib运行时,我得到了以下错误:

    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
        }
    }
    

    这似乎只在登录后发生,如果用户注册(并重定向回此页面),则不会发生此错误。

    如果有什么作用的话,我将标记库嵌套在一起。

    1 回复  |  直到 8 年前
        1
  •  4
  •   Vinay Prajapati Mahfujur Rahman    8 年前

    好正如日志所说 No session 。您使用的对象处于分离状态。因此,要么附加回对象,要么只通过id获取对象。

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

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

    编辑

    另一个解决方案是立即加载hasMany部分。但我不喜欢这种解决方案,因为它会减慢我的域名获取速度。此外,它还将获取has许多可能并非所有地方都需要的数据。