2013-05-28 33 views
0

我只有一个具有延迟加载实体控制器有问题(有发起并COMMITED交易,见堆栈跟踪)春天Hibernate的Transaction没有会话延迟加载

17:56:46,084 DEBUG HibernateTransactionManager:438 - Found thread-bound Session [[email protected]] for Hibernate transaction 
17:56:46,085 DEBUG HibernateTransactionManager:471 - Participating in existing transaction 
17:56:46,085 DEBUG HibernateTransactionManager:438 - Found thread-bound Session [[email protected]] for Hibernate transaction 
17:56:46,085 DEBUG HibernateTransactionManager:471 - Participating in existing transaction 
Hibernate: select preference0_.id as id66_, preference0_.name as name66_, preference0_.value as value66_, preference0_.default_value as default4_66_, preference0_.updated_at as updated5_66_ from preferences preference0_ where preference0_.name='scheduleInterval' 
17:56:46,086 DEBUG GooGooStatementCache:457 - cxnStmtMgr.statementSet([email protected]).size(): 21 
17:56:46,086 DEBUG GooGooStatementCache:196 - checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 111; checked out: 1; num connections: 10; num keys: 111 
17:56:46,087 DEBUG GooGooStatementCache:271 - checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 111; checked out: 0; num connections: 10; num keys: 111 
17:56:46,089 FATAL app:79 - service 
org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167) 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215) 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190) 
    at com.model.User_$$_javassist_76.getName(User_$$_javassist_76.java) 
    at com.model.json.ScheduleItemWrapper.wrap(ScheduleItemWrapper.java:55) 
    at com.web.controllers.ajax.Model.wrap(Model.java:127) 
    at com.web.controllers.ajax.Model.toJSON(Model.java:165) 
    at com.web.controllers.ajax.Model.getContent(Model.java:51) 
    at com.web.controllers.ajax.BasicAction.execute(BasicAction.java:27) 
    at com.web.HibernateServlet.doService(HibernateServlet.java:113) 
    at com.web.HibernateServlet.service(HibernateServlet.java:66) 
    at sun.reflect.GeneratedMethodAccessor200.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:695) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) 
    at com.levitech.web.controllers.schedule.ScheduleList$$EnhancerByCGLIB$$4a7ae33e.service(<generated>) 
    at com.levitech.web.RequestDispatcher.service(RequestDispatcher.java:63) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) 
    at java.lang.Thread.run(Thread.java:662) 
17:56:46,090 DEBUG HibernateTransactionManager:753 - Initiating transaction commit 
17:56:46,090 DEBUG HibernateTransactionManager:653 - Committing Hibernate transaction on Session [[email protected]] 
17:56:46,091 DEBUG HibernateTransactionManager:735 - Closing Hibernate Session [[email protected]] after transaction 
17:56:46,091 DEBUG SessionFactoryUtils:800 - Closing Hibernate Session 

模型(ScheduleItem和用户)和他们的休眠映射

public class ScheduleItem { 
    private Integer id; 
    .... 
    private User user; 

} 

public class User { 
    private Integer id; 
    ... 
    private String name; 

} 

<class 
    name="ScheduleItem" 
    table="schedule_item" 
> 

    <cache usage="read-write"/> 


    <id 
     name="id" 
     type="integer" 
     column="id" 
    > 
    <generator class="identity" /> 
    </id> 
    <many-to-one name="user" column="user_id" lazy="proxy"></many-to-one> 
</class> 

<class 
    name="ScheduleItem" 
    table="schedule_item" 
> 

    <cache usage="read-write"/> 


    <id 
     name="id" 
     type="integer" 
     column="id" 
    > 
    <generator class="identity" /> 
    </id> 
    <property name="name" column="name" type="string" /> 
</class> 

我发现的罪魁祸首。 OpenSessionViewFilter正在使用不同的会话或sessionfactory。

这是我的Spring配置和web.xml(我在做什么错?):

web.xml中的部分:

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

    <filter-mapping> 
    <filter-name>hibernateFilter</filter-name> 
    <url-pattern>/app/s/*</url-pattern> 
    </filter-mapping> 

Spring配置的部分:

<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
    <property name="driverClass" value="${db.driver}"/> 
    <property name="jdbcUrl" value="${db.url}"/> 
    <property name="user" value="${db.user}"/> 
    <property name="password" value="${db.pass}"/> 

     <!-- Pool properties --> 
    <property name="minPoolSize" value="5" /> 
    <property name="maxPoolSize" value="100" /> 
    <property name="acquireIncrement" value="5" /> 
    <property name="maxStatements" value="200" /> 
    <property name="idleConnectionTestPeriod" value="120" /> 
    <property name="maxIdleTime" value="1800" /> 

    </bean> 

     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="myDataSource"></property> 
     <property name="mappingLocations" value="classpath*:com/model/hbm/**/*.hbm.xml" /> 

    <property name="hibernateProperties"> 
     <value> 
     hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 
     hibernate.show_sql=true 
     hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory 
     hibernate.cache.use_query_cache=true 
     hibernate.cache.use_second_level_cache=true 
     </value> 
    </property> 
     </bean> 

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

回答

2

从日志看来,当您得到此异常时,会话仍处于打开状态。如果该行在数据库中不存在,则会出现这种异常的另一种情况。

User user = session.load(User.class, 1000); // Create a proxy 
user.getName(); // This would throw lazy initialization exception if row doesn't exist 

可以导致此问题的另一个场景是使用分离的对象。如果您获取并将ScheduleItem存储为HTTPSession变量。在另一个请求中检索它,然后尝试访问代理 - 它将导致相同的异常。用于加载对象的会话已关闭。如果是这种情况,则在使用它之前需要首先将对象重新附加到新的会话(合并,更新或锁定)。

+0

有趣的信息,但关联hibernate试图延迟加载为null(该行为空)没有什么需要加载。 ScheduleItem具有多对一映射的其他关联,这些关联在数据库中也是空的,并且不会产生问题。如果我为该特定关联添加fetch =“join”lazy =“false”,问题就会消失。我没有使用独立会话..我有一个会话每个请求 – user979051

+0

你可以交叉检查,因为它没有任何意义。如果user_id列的值为空值,那么ScheduleItem中的用户引用应该是空值 - 它根本不应该创建代理。从看起来不是这种情况的堆栈跟踪。你可以包含com.model.json.ScheduleItemWrapper.wrap的代码。 – gkamal

+0

感谢您让我走向正确的方向......我通过服务层上的aop进行事务管理,并且需要传播“新”的单个事务,事务在请求完成之前已提交(如预期的那样)并开了一个新的会议 – user979051

2

您的问题有多种解决方案:

  • 最简单的是使用Spring的OpenSessionInViewFilter。只需将此过滤器添加到您的web.xml并将其配置为过滤您的请求。 此过滤器在过滤器中打开和关闭Hibernate会话,因此在页面呈现会话期间将会打开。

  • 有人认为OpenSessionInViewFilter违背良好的设计,它将业务逻辑混合到表示层。如果您这么认为,请在您的查询中获取引用的对象(例如,在您的HQL中使用join fetch)。

+0

我已经试过了..不需要帮助 – user979051

+0

你可以写下你的实体和查询吗? –

-1

你可以尝试:

  • 急切加载集合。
  • 通过调用相应的getter方法Hibernate.initialize(rtn.getUserRoles());

那基本上两倍取决于什么最适合你的设置同样的方法在离开前集合初始化集合。确保在离开会话之前加载完整的实体,这样可以将实体从旧的分离出来,然后重新保存到新的会话中而没有问题。你正在做的是在离开会话之前初始化代理,以便当你不在会话上下文中时确保集合可用。

+0

为什么我想通过在我的服务服务或Web层中使用Hibernate特定的代码来公开我的dao实现?我可以轻松地抓取集合并避免这个问题,但总的来说,我确实希望按需缓存。 – user979051

+0

那么请说明有关您的交易和会话划分的信息以及抛出异常的上下文的问题,因为对于给出更多建议而非盲目尝试,这是必要的。 @theDownVoter:请说明投票的原因,以便我可以从我的错误中学习? – Carsten