2016-08-28 2 views
2

Я пытаюсь настроить тег lib, чтобы проверить, покупает ли пользователь продукт. Однако, когда мой TagLib запускается, я получаю эту ошибку:не удалось лениво инициализировать коллекцию роли: 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 

Вот мой тег Lib:

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

Это только похоже, происходит после входа в систему, если пользователь регистрируется вместо этого (и перенаправляется обратно на эту страницу), эта ошибка не происходит.

У меня есть теги libs, вложенные внутри друг друга, если это что-то делает.

ответ

3

Хорошо! Как говорят журналы, No session. Вы используете объект, находящийся в состоянии отсоединения. Следовательно, либо присоедините объект назад, либо просто выберите объект по id.

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

Или

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

И так, как вы будете прикрепить объект к сессии.

Редактировать

Другим решением может быть жадной нагрузкой hasMany части. Но я бы не предпочел это решение, так как это замедлит мою выборку домена. Кроме того, он будет извлекать данные hasMany, которые могут не потребоваться во всех местах.

+0

Зачем ему вводить это состояние? –

+1

Ну, может быть несколько причин. По моим сведениям, когда мы пытаемся выполнить любую операцию, связанную с БД, мы открываем сеанс и закрываем его. Здесь объект, который вы выбрали, - это HttpSession, у которого есть связанный тип Lazy. Это означает, что hasMany часть будет загружена из базы данных, когда это необходимо. Теперь, поскольку сеанс отсутствует, он не может лениться из базы данных. –

Смежные вопросы

 Смежные вопросы