延迟加载错误
我知道这个问题已经在这里提出几次了。然而,我找不到任何解决方案,因此我决定再次发布。延迟加载错误
我使用的是Spring MVC框架Hibernate和我想取我问心无愧类子类:
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
}
我的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;
}
and my spring mvc code:
@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
我GOOGLE了它,了解它是因为它试图获取作者在交易关闭和作者类是由懒人默认,但我不明白的是我应该如何修改我的代码,以便解决它。
任何建议更受欢迎。
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"])
Update3:
这是该操作的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=?
但笔者对象无线本地环路是静静空。
从控制器调用相同的getter会导致异常。
这可能是值得首先发布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配置。只是定义它是不够的,你需要:
<tx:annotation-driven transaction-manager="transactionManager"/>
=================================
从我在Hibernate文档中看到的情况来看,很可能一旦关闭事务,Hibernate会话就会结束(即使您使用OpenSessionInView过滤器)。 看一看这里: http://community.jboss.org/wiki/OpenSessioninView#Can_I_commit_the_transaction_before_rendering_the_view
一旦你关闭你的事务,数据库连接返回到池中,并在数据库中的所有进一步的访问将需要一个新的连接,它应该有自动提交模式下。
然而,在你的情况下,我认为解决方案是确保你已经加载了所有你需要从数据库加载,而交易仍然是开放的!
完成,但我不认为问题在那里,问题在我处理交易的方式,但无论如何,谢谢你提前。 – 2010-12-05 13:53:29