1

JSP我在从文件访问集合时遇到问题。应用程序基于 MVC Spring 框架。我把OpenSessionInViewFilter过滤器放到我的web.xml. 当我想使用提到的文件访问 URL 时,它会抛出我

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed

我在我的应用程序中使用域驱动设计。当我将类中的 fetch 类型Product从更改FetchType.LAZY为 时FetchType.EAGER,它起作用了。

堆栈跟踪

SEVERE: Servlet.service() for servlet [spring] in context with path [] threw exception [org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentSet.isEmpty(PersistentSet.java:169)
    at org.apache.el.parser.AstEmpty.getValue(AstEmpty.java:55)
    at org.apache.el.parser.AstNot.getValue(AstNot.java:44)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:185)
    at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:1026)
    at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fwhen_005f0(products_jsp.java:321)
    at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fchoose_005f0(products_jsp.java:290)
    at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fforEach_005f0(products_jsp.java:233)
    at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fif_005f0(products_jsp.java:185)
    at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspService(products_jsp.java:141)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet._serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:123)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
    at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:171)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1686)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

web.xml

  <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

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


<filter>
  <filter-name>OpenSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  <init-param>
    <param-name>sessionFactoryBeanName</param-name>
    <param-value>sessionFactory</param-value>
  </init-param>
  <init-param>
    <param-name>singleSession</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

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

<!-- Context parameters -->
  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>WEB-INF/log4j.properties</param-value>
  </context-param>
  <context-param>
    <param-name>log4jExposeWebAppRoot</param-name>
    <param-value>false</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>
</web-app>

spring-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
    http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<mvc:annotation-driven />
<tx:annotation-driven />
<context:component-scan base-package="com.app.cloud" />

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <property name="basename" value="spring-views" />
    <property name="order" value="1" />
</bean>

<bean id="jspViewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
    <property name="order" value="2" />
</bean>

<!-- JDBC -->
<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
    p:location="/WEB-INF/jdbc.properties" />

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />

<!-- Hibernate -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

产品服务.java

    @Transactional
    public interface ProductService {

        @Transactional
        public void add(Product product);
        @Transactional
        public List<Product> getAll();
        @Transactional
        public Product get(Integer idProduct);
        @Transactional
        public void remove(Integer id);
        @Transactional
        public void edit(Product product);

    }

ProductServiceImpl.java

@Service
@Transactional
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductDAO productDAO;

    @Transactional
    public void add(Product product) {
        productDAO.add(product);
    }

    @Transactional
    public List<Product> getAll() {
        return productDAO.getAll();
    }

    @Transactional
    public void remove(Integer id) {
        productDAO.remove(id);
    }

    @Transactional
    public Product get(Integer idProduct) {
        return productDAO.get(idProduct);
    }

    @Transactional
    public void edit(Product product) {
        productDAO.edit(product);
    }


}

ProductDAO.java

    public interface ProductDAO {

        public void add(Product product);
        public void edit(Product product);
        public List<Product> getAll();
        public Product get(Integer idProduct);
        public void remove(Integer id);

    }

ProductDAOImpl.java

@Repository
public class ProductDAOImpl implements ProductDAO {

    @Autowired
    private SessionFactory sessionFactory;

    public void add(Product product) {
        sessionFactory.getCurrentSession().save(product);
    }

    public List<Product> getAll() {
        return sessionFactory.getCurrentSession().createQuery("from Product")
                .list();
    }

    public void remove(Integer id) {
        Product product = (Product) sessionFactory.getCurrentSession().load(
                Product.class, id);
        if (null != product) {
            sessionFactory.getCurrentSession().delete(product);
        }
    }

    public Product get(Integer idProduct) {
        Product product = (Product) sessionFactory.openSession().get(
                Product.class, idProduct);
        return product;
    }

    @Override
    public void edit(Product product) {
        sessionFactory.getCurrentSession().update(product);
    }

}

产品.java

@Entity
@Table(name = "product", catalog = "app")
public class Product implements java.io.Serializable {

    private Integer idProduct;

    @NotEmpty
    @Length (min=1,max=70)
    private String name;

    private Set<Availability> availabilities = new HashSet<Availability>(0);

    public Product() {
    }

    public Product(String name) {
        this.category = category;
        this.name = name;
        this.lastUpdate = lastUpdate;
        this.actionFlag = actionFlag;
    }

    public Product(String name,
            Set<Availability> availabilities,
            ) {
        this.name = name;
        this.availabilities = availabilities;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id_product", unique = true, nullable = false)
    public Integer getIdProduct() {
        return this.idProduct;
    }

    public void setIdProduct(Integer idProduct) {
        this.idProduct = idProduct;
    }

    @Column(name = "name", nullable = false, length = 70)
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "product")
    public Set<Availability> getAvailabilities() {
        return this.availabilities;
    }

    public void setAvailabilities(Set<Availability> availabilities) {
        this.availabilities = availabilities;
    }

}
4

3 回答 3

5

使用 Hibernate 时,这是非常经典的错误。

@Transactional如果您有任何延迟加载代理,您应该在从上下文返回之前将它们替换为空值或真实对象。

延迟加载的SetorList被带有代理的 Hibernate 替换。代理将在第一次访问集合时加载它。但是,如果您在事务上下文之外首先访问它怎么办?代理引用的休眠会话不存在,因此您遇到错误。

如果您不需要该集合,请将其设置为 null 或空HashSet/ArrayList.如果您需要它,请size()在事务上下文中调用或迭代该元素。如果您不确定,请提供用于加载连接的 API。但不要返回带有未初始化代理的对象。

于 2013-06-24T14:47:19.163 回答
1

将您的注释Controller@Transactional. 你不会再看到那个错误了,你打赌!!

笔记

专家说@Transactional不能用Controller,但是我没有得到答案,为什么?

于 2013-06-25T06:03:02.790 回答
0

你可以试试

@Proxy (lazy = false)

在两个实体类之上。它适用于我的情况。

于 2013-06-24T15:05:53.730 回答