LazyInitializationException:懒得初始化一个角色集合无法初始化代理 - 没有Session

时间:2015-02-02 20:45:25

标签: spring hibernate spring-mvc spring-transactions

在SO中多次询问。但他们没有解决我的问题所以再次发布。

尝试访问我的应用程序时获取以下异常

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.wpt.models.Item.itemCategory, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:348)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:224)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:155)
    at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:256)

的web.xml

<filter>
        <filter-name>HibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>hibernate4AnnotatedSessionFactory</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>HibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Spring config:

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
    p:sessionFactory-ref="hibernate4AnnotatedSessionFactory">
</bean>

Item.java

@Entity
@Table(name="item")
public class Item {
    @OneToMany(mappedBy="item", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    private List<ItemCategory> itemCategory = new ArrayList<ItemCategory>();
}

ItemServiceImpl.java

@Override
    @Transactional(readOnly=true)
    public List<Item> getItemsByCategory(int categoryId) {
        return itemDAO.getItemsByCategory(categoryId);
    }

在所有博客中,建议您选择EAGER抓取,或使用OpenSessionInViewFilter支持@Transactional

如果我使用EAGER提取,它将起作用。但不是相反的方式。我已使用@Transactional注释实现了所有服务方法。我在这做什么错?有人可以帮忙吗?

4 个答案:

答案 0 :(得分:0)

首先,如果你做了一个急切的提取,你就会意识到会发生什么。这意味着当您请求项目时,对数据库的查询总是会带来itemCategory。也许这不是你期望的行为。

其次,发生了lazyInitialization异常,因为您在关闭会话后尝试访问对象itemCategory。我想当你从方法“getItemsByCategorymethod”收到List时会话被关闭。

我通常解决这种情况的方式(不是急切的获取)有两种方式:

  • 在关闭会话之前选择itemCategory。无论您何时致电执行查询,都可以说List listItemCategroy = item.getItemCategory()

  • 将fetch.JOIN添加到表itemCategory中,它将带来ItemCategory。

如果您想避免此错误,可以在代码中添加:

if (Hibernate.isInitilized()){
    ....
}

如果对象被初始化,它将返回true,否则返回false。

答案 1 :(得分:0)

好的,经过多次努力,我终于找到了解决这个问题的方法。

我已将contextConfigLocation添加到DispatcherServlet's <init-param>后问题得到解决。更改后,我的DispatcherServlet配置如下所示。

<servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

参考:This post

答案 2 :(得分:0)

contextConfigLocation用于指示xml文件(例如Spring,spring-security)所在的位置。

对我来说,使用Spring配置时,懒惰的问题没有任何意义。

你能详细解释一下吗?

答案 3 :(得分:0)

使用下面的过滤器而不是HibernateFilter

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

希望它会对你有所帮助。