Не удается исправить, не удалось лениво инициализировать набор ролей: не удалось инициализировать прокси - нет сеанса

Я получаю org.hibernate.LazyInitializationException, когда пытаюсь получить доступ к ленивым извлеченным атрибутам моих классов, в вызове jsp forEach и в классе контроллера.

Я прочитал все предыдущие ответы и попробовал их, я добавил @Transactional в свою службу и методы классов dao, которые его используют, просто чтобы быть уверенным, я попытался добавить Hibernate.initialize(), не работал, а позже фильтр, но это делает мой производительность хуже, чем при нетерпеливом извлечении. Это работает, когда я меняю его на нетерпеливую выборку, но я хочу, чтобы она была ленивой из-за производительности. В основном ошибка возникает, когда absoluteRatingVal() вызывается в строке цикла for. все как в статье, так и в рейтинге ленивое.

Статья.java

@Entity
@Table(name = "articles")
public class Article {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private int id;

   @Column(name = "title")
   private String title;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "created_by")
   private User user;

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "article", fetch = FetchType.LAZY)
   private Set<Rating> rating = new HashSet<>();

public Double getAbsoluteRatingVal() {

    double rating = 0;
    Set<Rating> ratings = getRating();
    for (Rating r : ratings) {
        if (Days.daysBetween(new DateTime(r.getDate().getTime()), new DateTime(new Date().getTime()))
                .getDays() < 301)
            if (r.getGenuine() != null)
                rating++;
            else if (r.getOpinion() != null)
                rating++;
    }

    if (ratings.size() > 0)
        return rating;

    return null;
}
}

NewsDao.java с 1 примером метода, который вызывает эту ошибку.

@Repository("newsDao")
@Transactional
@Component("newsDao")
public class NewsDao {
    @Autowired
    private SessionFactory sessionFactory;
    private Transaction tx;

    public Session session() {
        return sessionFactory.openSession();
    }

    @Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)
    public List<Article> searchArticlesByRating(String query) {
    Session session = session();
    try {
        CriteriaBuilder builder = session.getCriteriaBuilder();
        CriteriaQuery<Article> crit = builder.createQuery(Article.class);
        Root<Article> root = crit.from(Article.class);
        crit.select(root).where(builder.like(root.get("title"), "%" + query + "%"));
        Query<Article> q = session.createQuery(crit);

        List<Article> result = q.list();
        session.close();

        System.err.println(result);         

        Rating fake = new Rating();
        fake.setDate(new Date());
        fake.setFake(new User());
        for (Article a : result) {
            if (a.getAbsoluteRatingVal() == null) 
                a.getRating().add(fake);
        }

        Collections.sort(result,
                Comparator.comparing(Article::getAbsoluteRatingVal).thenComparing(new Comparator<Article>() {
                    public int compare(Article a1, Article a2) {
                        if (a1.getRating() != null && a2.getRating() != null)
                            return a2.getRating().size() - a1.getRating().size();
                        return 0;
                    }
                }));

        for (Article a : result) {
            if (a.getAbsoluteRatingVal() != null && a.getAbsoluteRatingVal().intValue() == 0) 
                a.getRating().remove(fake);
        }

        return result;
    } catch (Exception e) {
        e.printStackTrace();

        session.close();
        return null;
    }
}

Рейтинг.java

@Entity
@Table(name = "ratings")
public class Rating {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "article")
    private Article article;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "voted_genuine")
    private User genuine;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "voted_fake")
    private User fake;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "voted_opinion")
    private User opinion;
 }

ИЗМЕНИТЬ

В Featured.jsp я получаю эту ошибку: org.hibernate.LazyInitializationException: не удалось инициализировать прокси - нет сеанса, когда я вызываю article.user.isSubscribed(), который обращается к отношению OneToOne, насколько я понимаю, пользователь является нулевым, потому что он не может быть принес.

признакам.jsp

<c:choose>
                            <c:when
                                test='${article.user.isSubscribed() and article.user.subscription.type eq "silver" }'>
                                <a class="bold"
                                    href='${pageContext.request.contextPath}/u/${article.user.username}'><span
                                    class="silvername"> <c:out value="${article.user.name}"></c:out></span></a>
                            </c:when>
                            <c:when
                                test='${article.user.isSubscribed() and article.user.subscription.type eq "gold" }'>
                                <a class="bold"
                                    href='${pageContext.request.contextPath}/u/${article.user.username}'><span
                                    class="goldname"> <c:out value="${article.user.name}"></c:out></span></a>
                            </c:when>
                            <c:when
                                test='${article.user.isSubscribed() and article.user.subscription.type eq "premium" }'>
                                <a class="bold"
                                    href='${pageContext.request.contextPath}/u/${article.user.username}'><span
                                    class="premiumname"> <c:out
                                            value="${article.user.name}"></c:out></span></a>
                            </c:when>
                            <c:otherwise>
                                <a class="bold"
                                    href='${pageContext.request.contextPath}/u/${article.user.username}'><span>
                                        <c:out value="${article.user.name}"></c:out>
                                </span></a>
                            </c:otherwise>
                        </c:choose>

Я хочу, чтобы приложение работало с отложенной выборкой


person DisplayName    schedule 20.12.2018    source источник


Ответы (1)


Вызовите session.close() непосредственно перед возвратом из NewsDao#searchArticlesByRating(String), т.е. после вызова Article#getAbsoluteRatingVal().

@Transactional(...)
public List<Article> searchArticlesByRating(String query) {
    Session session = session();
    try {
        // business logic here

        session.close();   

        return result;

    } catch (Exception e) {
    }
}
person Minar Mahmud    schedule 20.12.2018
comment
Большое спасибо, Махмуд, это решило эту проблему, но возникла другая с тем же исключением, на этот раз в моем jsp. Я добавляю редактирование, чтобы объяснить новую ошибку. - person DisplayName; 21.12.2018
comment
@DisplayName, в чем новая проблема? - person Minar Mahmud; 21.12.2018
comment
Если это та же проблема для уровня представления, см. этот OpenSessionInViewInterceptor [docs.spring.io/spring-framework/docs/current/javadoc-api/org/ - person Minar Mahmud; 21.12.2018
comment
Я добавил @Bean для OpenSessionInViewInterceptor, но не могу найти способ использовать addInterceptors(InterceptorRegistry) или любой другой способ заставить его выполняться. Вы знаете решение? Заранее спасибо. - person DisplayName; 21.12.2018
comment
@DisplayName Боюсь, мне нужно увидеть подробный код. Вы можете опубликовать другой вопрос, если это поможет! И также не стесняйтесь принимать это, если это решило конкретную проблему, о которой вы спрашивали! Спасибо! - person Minar Mahmud; 21.12.2018
comment
Эй, Махмуд, большое спасибо за вашу помощь до сих пор. Я задал следующий вопрос здесь: весна mvc"> stackoverflow.com/questions/53888513/ - person DisplayName; 21.12.2018
comment
@DisplayName всегда пожалуйста. Я рассмотрю вопрос, посмотрим, смогу ли я помочь. - person Minar Mahmud; 21.12.2018