2010-12-05 4 views
1

Я знаю, что эта проблема уже была поднята здесь несколько раз. Однако я не мог найти решение, которое поможет, поэтому я решил опубликовать его снова.Lazy Ошибка при загрузке

Я использую Hibernate с основой Spring MVC, и я пытаюсь забрать свой класс WTH суб-класс:

public class Scene implements Serializable{ 
private Long id; 
private Author author; 
//omitting getters and setters 
} 

public class Author{ 
private Long id; 
Private String name; 
//omitting getters and setters 
} 

конфигурацию My Hibernate является следующее:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="org.postgresql.Driver" /> 
    <property name="url" value="jdbc:postgresql://127.0.0.1/doolloop2" /> 
    <property name="username" value="doolloop2" /> 
    <property name="password" value="doolloop" /> 
</bean> 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="mappingLocations"> 
     <list> 
     <value>WEB-INF/mapping/Scene.hbm.xml</value> 
     <value>WEB-INF/mapping/Author.hbm.xml</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
<props> 
    <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> 
    <prop key="hibernate.show_sql">true</prop> 
    <prop key="hibernate.hbm2ddl.auto">update</prop> 
    <prop key="hibernate.cache.use_second_level_cache">true</prop> 
    <prop key="hibernate.cache.use_query_cache">true</prop> 
    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> 
    </props> 
    </property> 
</bean> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<bean id="txService" class="com.doolloop.services.TxDataBaseServiceImpl"> 
     <property name="sessionFactory"> 
     <ref local="sessionFactory"/> 
     </property> 
    </bean> 

Теперь у меня есть методы, которые получают мою сцену:

@Override 
    @Transactional(readOnly = true) 
    public Scene getScene(Long id) { 
     Session session = this.sessionFactory.getCurrentSession(); 
     Query q = session.createQuery("select scene from com.doolloop.objects.Scene scene where scene.id=:id"); 
     q.setLong("id", id); 
     Scene scene = (Scene)q.uniqueResult() 
     return scene; 

    } 

и мой Spring MVC код:

@RequestMapping(value="/getSceneMetaData.dlp",method = RequestMethod.GET) 
    @ResponseBody 
    public Scene getSceneMetaData(@RequestParam String id){ 
     Scene scene = service.getScene(Long.parseLong(id)); 
     return scene; 
    } 

Когда я его выполнением я получил followng исключения:

Dec 5, 2010 12:29:21 PM org.hibernate.LazyInitializationException <init> 
    SEVERE: failed to lazily initialize a collection of role: com.doolloop.objects.Scene.author, no session or session was closed 
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.doolloop.objects.Scene.vauthor, no session or session was closed 

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

Любое предложение более приветствуется.

UPD: вот файлы отображения для обоих классов:

<class 
     name="com.doolloop.objects.Scene" 
     table="scene" 
    > 
     <id 
      name="id" 
      column="Id" 
      type="java.lang.Long" 
      unsaved-value="null" 
     > 
     <generator class="sequence"> 
       <param name="sequence">doolloop2.sceneseq</param> 
      </generator> 
     </id> 
    <many-to-one 
     name="author" 
     class="com.doolloop.objects.Author" 
     cascade="all" 
     column="authorid" 
     unique="false" 
    /> 
    </class> 

<hibernate-mapping> 
    <class 
     name="com.doolloop.objects.Author" 
     table="authors" 
    > 
     <id 
      name="id" 
      column="Id" 
      type="java.lang.Long" 
      unsaved-value="null" 
     > 
     <generator class="sequence"> 
       <param name="sequence">doolloop2.authorseq</param> 
      </generator> 
     </id> 
     <property 
      name="name" 
      update="true" 
      insert="true" 
      not-null="false" 
      unique="false" 
      type="java.lang.String" 
     > 
      <column name="name" /> 
     </property> 
      <property 
      name="email" 
      update="true" 
      insert="true" 
      not-null="false" 
      unique="false" 
      type="java.lang.String" 
     > 
      <column name="email" /> 
     </property> 
     <property 
      name="site" 
      update="true" 
      insert="true" 
      not-null="false" 
      unique="false" 
      type="java.lang.String" 
     > 
      <column name="site" /> 
     </property> 
     <property 
      name="contactInfo" 
      update="true" 
      insert="true" 
      not-null="false" 
      unique="false" 
      type="java.lang.String" 
     > 
      <column name="contactInfo" /> 
     </property> 
    </class> 

UPD2 Я добавил следующее к моей web.xml:

<listener> 
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>WEB-INF/applicationContext.xml</param-value> 
</context-param> 
    <filter> 
    <filter-name>openSessionInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>openSessionInViewFilter</filter-name> 
    <url-pattern>/getSceneMetaData.dlp</url-pattern> 
</filter-mapping> 

он дал мне следующее исключение:

org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.doolloop.objects.Scene["author"]->com.doolloop.objects.Author_$$_javassist_4["name"]) 

Обновление3:

Это выход log4j для этой операции:

2010-12-06 11:48:09,031 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] - Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter 
2010-12-06 11:48:09,036 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'sessionFactory' 
2010-12-06 11:48:09,040 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] - Opening single Hibernate Session in OpenSessionInViewFilter 
2010-12-06 11:48:09,042 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session 
2010-12-06 11:48:09,048 DEBUG [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'doolloop' processing GET request for [/dlp/getSceneMetaData.dlp] 
2010-12-06 11:48:09,056 DEBUG [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapping [/getSceneMetaData.dlp] to HandlerExecutionChain with handler [[email protected]] and 2 interceptors 
2010-12-06 11:48:09,060 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Last-Modified value for [/dlp/getSceneMetaData.dlp] is: -1 
2010-12-06 11:48:09,142 DEBUG [org.springframework.core.convert.support.GenericConversionService] - Converting value '140' of [TypeDescriptor java.lang.String] to [TypeDescriptor @org.springframework.web.bind.annotation.RequestParam java.lang.String] 
2010-12-06 11:48:09,146 DEBUG [org.springframework.core.convert.support.GenericConversionService] - Converted to '140' 
2010-12-06 11:48:09,148 DEBUG [org.springframework.web.bind.annotation.support.HandlerMethodInvoker] - Invoking request handler method: public com.doolloop.objects.Scene com.doolloop.controllers.SceneController.getSceneMetaData(java.lang.String) 
2010-12-06 11:48:16,401 DEBUG [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver] - Resolving exception from handler [[email protected]]: org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.doolloop.objects.Scene["author"]->com.doolloop.objects.Author_$$_javassist_4["name"]) 
2010-12-06 11:48:16,561 DEBUG [org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver] - Resolving exception from handler [[email protected]]: org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.doolloop.objects.Scene["author"]->com.doolloop.objects.Author_$$_javassist_4["name"]) 
2010-12-06 11:48:16,568 DEBUG [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] - Resolving exception from handler [[email protected]]: org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.doolloop.objects.Scene["author"]->com.doolloop.objects.Author_$$_javassist_4["name"]) 
2010-12-06 11:48:16,572 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Could not complete request 
org.codehaus.jackson.map.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.doolloop.objects.Scene["author"]->com.doolloop.objects.Author_$$_javassist_4["name"]) 
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:215) 

//// Entire stack trace goes here. 

2010-12-06 11:48:16,660 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] - Closing single Hibernate Session in OpenSessionInViewFilter 
2010-12-06 11:48:16,662 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session 

Update4:

Я вижу только один выбор п консоли:

Hibernate: select scene0_.Id as Id20_0_, scene0_.name as name20_0_, scene0_.description as descript3_20_0_, scene0_.defaultView as defaultV4_20_0_, scene0_.authorid as authorid20_0_ from scene scene0_ where scene0_.Id=? 

Однако, если я изменить мой getScene метод таким образом:

public Scene getScene(Long id) { 
     Session session = this.sessionFactory.getCurrentSession(); 
     Query q = session.createQuery("select scene from com.doolloop.objects.Scene scene where scene.id=:id"); 
     q.setLong("id", id); 
     Scene scene = (Scene)q.uniqueResult() 
     **Author author = scene.getAuthor();** 
     return scene; 

Я вижу второй выбор появляется:

Hibernate: select author0_.Id as Id23_0_, author0_.name as name23_0_, author0_.email as email23_0_, author0_.site as site23_0_, author0_.contactInfo as contactI5_23_0_ from authors author0_ where author0_.Id=? 

но объект автор WLL быть еще пуст.

, вызывающий один и тот же геттер от контроллера, вызывает исключение.

ответ

7

Возможно, стоит опубликовать Scene.hbm.xml и Author.hbm.xml вначале ..

Из того, что я видел здесь: https://forum.hibernate.org/viewtopic.php?f=1&t=994772&start=0 Много-к-одному отношения загружаются Жадно по умолчанию, если вы используете аннотации, однако, что это не то, что происходит, если вы используете XML сопоставления !!

Я бы сказал, измените отношения «много-к-одному» и явно установили fetch="EAGER".

Так что результат должен быть:

<many-to-one 
    name="author" 
    class="com.doolloop.objects.Author" 
    cascade="all" 
    column="authorid" 
    unique="false" 
    fetch="EAGER" 
/> 

Вы упомянули, что у вас есть 2 сценариев использования: один, где вы запрашиваете объект сцены и вам нужно все свои зависимости и тот, где вы заинтересованы только в id и несколько полей для него. Кажется, это вопрос определения границ сеанса Hibernate. Вы можете использовать описанный здесь SessionInViewFilter: http://community.jboss.org/wiki/OpenSessioninView Таким образом, сеанс Hibernate будет открыт на время HTTP-запроса, так что вы сможете получить доступ к ленивым загружаемым ссылкам, чтобы отображать время. Помогает ли это?

=================================
Я видел ваше определение OpenSessionInViewFilter - это, возможно, стоит явно устанавливая имя вашего HibernateSessionFactory:

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

Кроме того, я не вижу надлежащей инициализации менеджера вашего Tx в вашей Spring Config. Просто определение этого недостаточно, вам нужно:

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

=================================
Из того, что я видел в документации Hibernate, очень вероятно, что после закрытия транзакции сеанс Hibernate завершится (даже если вы используете OpenSessionInView Filter). Посмотрите здесь: http://community.jboss.org/wiki/OpenSessioninView#Can_I_commit_the_transaction_before_rendering_the_view

После того, как вы закрываете транзакцию, то соединение БД возвращается в пул и все дальнейший доступ к БД потребуется новое соединение, которое должно иметь автоматический режим фиксации на ,

Однако, в вашем случае, я думаю, что решение должно состоять в том, чтобы убедиться, что вы загрузили все, что вам нужно загрузить из БД, пока транзакция по-прежнему открыта!

+0

Выполнено, но я не думаю, что проблема там, проблема s в том, как я обрабатываю транзакцию, но в любом случае спасибо вам заранее. – 2010-12-05 13:53:29

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