Spring MVC JPA ленивое исключение - PullRequest
1 голос
/ 18 апреля 2011

Я использую JPA Hibernate и Spring MVC. Я реализовал шаблон хранилища. Я получаю PageRepository, который просто получает объект Page из БД. Затем в контроллере я пытаюсь получить доступ к pageObject.getWidgets () (определяется как ленивый), и я получаю исключение о том, что сессия закрыта.

Просто чтобы прояснить, вот код контроллера

@RequestMapping(value = "/pages/get",method=RequestMethod.GET)
    public @ResponseBody String getPage(@RequestParam Long id){
        .....
            Page page = pageRepository.getById(id);
            if(page!=null && page.getWidgets()!=null){
                for(Widget widget: page.getWidgets()){ <--- here the exception occurs
                    ....    }

простой код репозитория

@PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

    protected abstract Class<T> getConcreteClass();

    @Override
    public T getById(long id) {
        return em.find(getConcreteClass(), id);
    }

модель по отношению к виджетам

@OneToMany(fetch=FetchType.LAZY,orphanRemoval=true,cascade=CascadeType.ALL,mappedBy="page")
    public List<Widget> getWidgets() {
        return widgets;
    }

    public void setWidgets(List<Widget> widgets) {
        this.widgets = widgets;
    }

my web.xml

 <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>Spring3MVC</display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>
            com.opensymphony.module.sitemesh.filter.PageFilter
        </filter-class>
      </filter>
    <filter-mapping>
        <filter-name>sitemesh</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>*.html</url-pattern>
      </servlet-mapping>
      <servlet>
        <servlet-name>Resource Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>Resource Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
      </servlet-mapping>
      <!-- 
      Spring Security
      -->

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                ...
            </param-value>
        </context-param>

        <filter>
          <filter-name>springSecurityFilterChain</filter-name>
          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>

        <filter-mapping>
          <filter-name>springSecurityFilterChain</filter-name>
          <url-pattern>/*</url-pattern>
        </filter-mapping>
        <!-- 
        Spring Security
        -->

        <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>


    </web-app>

мой весенний сервлет

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


   ....
    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
        <property name="defaultLocale" value="es"/>
    </bean>

    <bean id="handlerMapping"
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <ref bean="localeChangeInterceptor" />
        </property>
    </bean>


    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     ...
    </bean>

    <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="dataSource"
    p:jpaVendorAdapter-ref="jpaAdapter">
        <property name="loadTimeWeaver">
                <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>                             
        <property name="persistenceUnitName" value="sparkPersistenceUnit"></property>
    </bean>

     <bean id="jpaAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:database="MYSQL"
    p:showSql="true"
    p:generateDdl="true"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory"/>

    <tx:annotation-driven transaction-manager="transactionManager"/>



</beans>

Исключение

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.model.Page.widgets, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
    at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
    at com.sprekelia.spark.controller.PageController.getPage(PageController.java:78)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:312)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:95)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:165)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Ну, что я могу сделать, чтобы решить эту проблему?

Заранее спасибо

Ответы [ 2 ]

4 голосов
/ 18 апреля 2011

Вы не использовали чистый JPA, но JPA через Hibernate, и для того, чтобы ленивая загрузка работала, вам нужно добавить аннотацию @Transactional в свой метод.Это приведет к тому, что соединение останется открытым в течение всего жизненного цикла метода.

Методы контроллера не вызываются извне и поэтому не подлежат прокси, на которые опирается @Transactional.Может потребоваться переместить код обхода графа сущностей в класс «Service» и применить там @Transactional.

2 голосов
/ 19 апреля 2011

Спасибо всем.Я решил проблему написания кода внутри компонента или службы.Таким образом, я могу использовать @Transactional без проблем.

вот код

контроллер метода

@RequestMapping(value = "/pages/get",method=RequestMethod.GET)
    public @ResponseBody String getPage(@RequestParam Long id){
        return new Gson().toJson(new ActionResult(pageBuilderService.buildAdapterFromPage(id)));
    }

служба

@Component(value="PageBuilderService")
public class PageBuilderService {

    @Autowired
    private IPageRepository pageRepository;


    public void setPageRepository(IPageRepository pageRepository) {
        this.pageRepository = pageRepository;
    }

    @Transactional
    public List<WidgetAdapter> buildAdapterFromPage(Long pageId){
        List<WidgetAdapter> adapters = new ArrayList<WidgetAdapter>();
        if(pageId!=null){
            Page page = pageRepository.getById(pageId);
            if(page!=null && page.getWidgets()!=null){
                for(Widget widget: page.getWidgets()){
                    adapters.add(WidgetFactory.FactoryMethodAdapter(widget));
                }
            }
        }
        return adapters;
    }

}

, котораяэто решение, которое я получаю с предоставленной информацией.Я не знаю, является ли это лучшим, но я думаю, что это хорошее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...