1

我只有一个具有延迟加载实体的控制器有问题(有一个事务已启动并提交,请参阅堆栈跟踪)

17:56:46,084 DEBUG HibernateTransactionManager:438 - Found thread-bound Session [org.hibernate.impl.SessionImpl@6b204e88] 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 [org.hibernate.impl.SessionImpl@6b204e88] 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( com.mysql.jdbc.JDBC4Connection@5ec60ee2 ).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 [org.hibernate.impl.SessionImpl@6b204e88]
17:56:46,091 DEBUG HibernateTransactionManager:735 - Closing Hibernate Session [org.hibernate.impl.SessionImpl@6b204e88] after transaction
17:56:46,091 DEBUG SessionFactoryUtils:800 - Closing Hibernate Session

模型(ScheduleItem 和 User)及其休眠映射

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 正在使用不同的会话或会话工厂。

这是我的 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>
4

3 回答 3

2

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

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

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

于 2013-05-28T22:13:15.913 回答
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 变量。在另一个请求中检索它,然后尝试访问代理 - 这将导致相同的异常。用于加载对象的会话已关闭。如果是这种情况,您需要先将对象重新附加到新会话(合并、更新或锁定),然后再使用它。

于 2013-05-30T02:15:17.803 回答
-1

您可以尝试:

  • 急切地加载集合。
  • 通过调用相应的 getter 方法在离开集合之前初始化集合Hibernate.initialize(rtn.getUserRoles());

这基本上是相同方法的两倍,具体取决于您的设置中最有效的方法。您确保在离开会话之前加载完整的实体,这样实体就可以从旧会话中分离出来,然后重新连接到新会话而不会出现问题。您正在做的是在离开会话之前初始化代理,以便在您离开会话上下文时可以确定该集合。

于 2013-05-29T06:53:15.907 回答