我的SSH项目之旅(6.session问题解决)

2008年08月07日 JAVA 评论 14 条

 

2008-07-20 22:25:27,531 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2008-07-20 22:25:27,609 INFO [org.springframework.jdbc.support.SQLErrorCodesFact

ory] - SQLErrorCodes loaded: [DB2, HSQL, MS-SQL, MySQL, Oracle, Informix, PostgreSQL, Sybase]


2008-07-20 22:26:48,437 WARN [org.hibernate.jdbc.ConnectionManager] - finalizingwith closed connection
2008-07-20 22:26:48,437 WARN [org.hibernate.jdbc.ConnectionManager] - unclosed connection, forgot to call close() on your session?




Hibernate: select item0_.itemid as itemid, item0_.itemname as itemname1_, item0_.itemcode as itemcode1_ from item item0_
2008-07-22 20:54:56,375 WARN [org.hibernate.jdbc.ConnectionManager] – finalizing with closed connection


2008-07-22 20:56:32,812 WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: 0, SQLState: null
2008-07-22 20:56:32,812 ERROR [org.hibernate.util.JDBCExceptionReporter] - Cannot get a connection, pool error Timeout waiting for idle object
2008-07-22 20:56:32,828 WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: 0, SQLState: null
2008-07-22 20:56:32,828 ERROR [org.hibernate.util.JDBCExceptionReporter] - Cannot get a connection, pool error Timeout waiting for idle object
org.hibernate.exception.GenericJDBCException: Cannot open connection

终于找到解决办法了 ,我们来看下面的内容吧
ItemDAOImpl.java
public class ItemDAOImpl extends HibernateDaoSupport implements ItemDAO {

  public List queryAll() throws Exception {
    // TODO Auto-generated method stub
    Session session=super.getSession(true);
    String hql="from Item as i";
    List l=super.getSession().createQuery(hql).list();
    return l;
}
}
其实上面的代码隐藏了一个问题,数据库连接并没有被关闭,所以一直出现以上的问题。
我这里提供三个解决方案
方案一:
用此种方法,虽然没有手动关闭数据库连接,但spring已经帮我们关闭了
return super.getHibernateTemplate().find(hql);
方案二:(经测试,此方案比较有效)
设定HibernateTemplateAllowCreateTrue
spring API HibernateDaoSupport
protected net.sf.hibernate.Session getSession(boolean allowCreate)
      Get a Hibernate Session, either from the current transaction or a new one.
public class ItemDAOImpl extends HibernateDaoSupport implements ItemDAO {

  public List queryAll() throws Exception {
    // TODO Auto-generated method stub
    Session session=super.getSession(true);
    String hql="from Item as i";
      List l=session.createQuery(hql).list();
    try{
      return l;
    }finally{
  &nb
sp;
session.close();
    }
}
}
方案三:
Spring API:
geSession()
org.springframework.orm.hibernate3.support.HibernateDaoSupport 中的一个方法,

它可以从当前事务或者一个新的事务获得一个hibernate 
session.
通常使用releaseSession(org.hibernate.Session)方法与getSession()配合。

如果没有绑定线程,releaseSession关闭由这个DAOSessionFactory创建的Hibernate Session。 
修改后的代码如下:

public class ItemDAOImpl extends HibernateDaoSupport implements ItemDAO {
  public List queryAll() throws Exception {
    // TODO Auto-generated method stub
    Session session = super.getSession();
    String hql = "from Item as i";
    List l = session.createQuery(hql).list();
    releaseSession(session);

  }
}
困扰了几天的问题终于解决了,项目搁浅了好几天了,就是对springsession的管理不清楚。

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: dj.fantlam.myssh.vo.Item.subitems - no session or session was closed

这是一个关于延迟加载的问题
applicationContext.xml加入
<bean id="hibernateInterceptor"
  class="org.springframework.orm.hibernate3.HibernateInterceptor">
    <property name="sessionFactory">
      <ref bean="sessionFactory" />
    </property>
  </bean>
在业务逻辑层中使用延迟加载
  
即使在视图外面,Spring框架也通过使用AOP 拦截器 HibernateInterceptor来使得延迟加载变得很容易实现。这个Hibernate 拦截器透明地将调用配置在Spring应用程序上下文中的业务对象中方法的请求拦截下来,在调用方法之前打开一个Hibernate会话,然后在方法执行完之后将会话关闭。



以及 Item.hbm.xml  
<set name="subitems" inverse="true" cascade="all” talbe=”subitem” 表示一对多 lazy="false" order-by="subcode">
        <key>
          <column name="itemid" />
        </key>
        <one-to-many cl

ass="dj.fantlam.myssh.vo.Subitem" />

    </set>
问题得以解决

上网查了一些资料
hibernate一对多session关闭问题
  <filter>
    <filter-name>opensession</filter-name>
    <filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>opensession</filter-name>
    <url-pattern>*.do</url-pattern>
  </filter-mapping>
openSessionInView的意思就是延长session的生命周期,到了jsp层,session依然有效,所以就可以正确读取一对多的多方的属性值了

2008-07-25 21:47:31,031 ERROR [org.apache.catalina.core.ContainerBase.[Catalina]
.[localhost].[/myssh].[jsp]] - Servlet.service() for servlet jsp threw exception

java.lang.IllegalStateException: getOutputStream() has already been called for this response

原因是image.jsp的问题   由于jsp container在处理完成请求后会调用releasePageContet方法释放所用的PageContext object,并且同时调用getWriter方法,由于getWriter方法与在jsp页面中使用流相关的getOutputStream方法冲突,所以会造成这种异常,

解决方法 在最后加上

out.clear();
out = pageContext.pushBody();


Question.hbm.xml
  <set name="answers" inverse="true" table="answer">
        <key>
          <column name="qid" />
        </key>
        <one-to-many class="dj.fantlam.myssh.vo.Answer" />
    </set>




刚刚在http://localhost:8888/myssh/jsp/show.do?qid=6&status=selectid这块出现了延迟加载的问题,也就是question_show.jsp
  <logic:iterate id="ans" name="question" property="answers">
  </logic:iterate> answers的时候没读到
然后我在Question.hbm.xml加上lazy="false"就行了
<set name="answers" inve

rse="true" table="answer" lazy="false">

        <key>
          <column name="qid" />
        </key>
        <one-to-many class="dj.fantlam.myssh.vo.Answer" />
</set>


今天我又发现了一个问题,原来之前的解决方案是多余的。我就是觉得很奇怪,前段日子就是怎么测都是session关闭了,真的很莫名其妙。实际上OpenSessionInViewFilter这个配置就是解决在websession的问题,而之前我配了之后不起作用,现在想想原因应该是tomcat里的项目之间的干扰吧,因为如今我把一些别的项目去掉了,问题就没了(不过当时我是有在虚拟机做测试的,一个新的tomcat也同样出问题,百思不得其解,再测试一下再说吧,以后有问题再补充)。害得我走了冤枉路,还到论坛里问了许久。总结一下,就是利用hibernateTemplate或者是直接利用hibernateDAOSupport类来取得session 这两种方法都可以自动处理session的,前一种是spring机制,而后一种是hibernate机制。
2008-08-06 17:15:13,272 INFO [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] - Initializing filter 'opensession'
2008-08-06 17:15:13,444 INFO [org.springframework.core.CollectionFactory] - JDK 1.4+ collections available
2008-08-06 17:15:13,475 INFO [org.springframework.core.CollectionFactory] - Commons Collections 3.x available
2008-08-06 17:15:13,490 INFO [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] - Filter 'opensession' configured successfully
经过测试 不配置OpenSessionInViewFilter的话在网页读取的时候就会发生session问题



网上有这么一种说法
---------------------------------------------------------------------------------------------------
strutsspring的整合是在struts-config.xml里加了个plugin
<plug-in
  className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation"
      value="/WEB-INF/classes/applicationContext.xml" />
  </plug-in>
这一段必须去掉
web.xml加上
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
保证openSessionInView的正常使用
经过我的测试,此方法有道理。我们先来看看spring整合struts的方法吧。两者整合的一种通用配置:在web.xml中加入一下任意一种
1
  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

2
  <servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>
    org.springframework.web.context.ContextLoaderServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

为了让spring ApplicationContext实例化,作为IOC容器,必须优先加载,一种常见的做法是在web.xml加载spring容器。所以以上2种方法都是一样的,ContextLoaderListenerContextLoaderServlet底层都依赖ContextLoader,因此两者效果几乎没有什么区别。在Servlet2.3标准中才出现ContextLoaderListener,它比ContextLoaderServlet会优先加载。

现在我得出的结论是之前是OpenSessionInViewFilter不起作用,如果我不把plugin
去掉的话问题依旧。经过测试,我不加plugin问题就没了。(若以后有相关问题再继续讨论)

14 条留言  访客:0 条  博主:0 条

  1. 我已经加了session.close();还是出现了WARN – finalizingwith closed connection。之后如果要和数据库打交道,就卡在那里了。请指教。谢谢!

  2. 受教了

  3. avatar nike shoes

    写的不错!留个脚印

  4. 难怪我用OpenSessionInViewFilter没用,原来是plug-in没删

  5. Fed up with obtaining low numbers of useless visitors to your site? Well i want to inform you of a new underground tactic that makes myself $900 each day on 100% AUTOPILOT. I could be here all day and going into detail but why dont you merely check their site out? There is really a great video that explains everything. So if your serious about producing quick money this is the site for you. Auto Traffic Avalanche

  6. Another excellent article! Thank you!

  7. Awesome post and must say it got my attention. I was browsing online and saw your site and am glad i found it.

  8. Another excellent article! Thank you!

  9. Another excellent article! Thank you!

  10. Once Once more great post. You Appear to have a Excellent Knowing of these themes.When I entering your blog,I felt this .

  11. 嗯。。很不错哦。

  12. 显然是有很多了解。我认为,在一些功能好点的也。继续努力,伟大的工作!

  13. Yo son de san mateo y la verdad de errtnaeme de este asesinato asta se me quitan las ganas de regresar ami pueblo querido.yo le pido atodos los pineros que ya se unan y no se lo pasan peleando por el puesto y que tratan de tener mas vigilados a los ninos de depradadores como este y alos padres k no dejen solos a sus hijos por tanto tiempo.yo que kisiera que fuera como en e.u.k no podemos dejarlos en el carro ni por un minuto solos.yo tengo tres y los cuido mas que mi propia vida ..mi mas sentido pesame a la familia lopezhttp://www.gatchina.biz/item/113.htmlhttp://www.gatchina.biz/vektorhttp://www.gatchina.biz/item/113/20.htmlhttp://www.gatchina.biz/juristhttp://www.gatchina.biz/audit

  14. Yo son de san mateo y la verdad de errtnaeme de este asesinato asta se me quitan las ganas de regresar ami pueblo querido.yo le pido atodos los pineros que ya se unan y no se lo pasan peleando por el puesto y que tratan de tener mas vigilados a los ninos de depradadores como este y alos padres k no dejen solos a sus hijos por tanto tiempo.yo que kisiera que fuera como en e.u.k no podemos dejarlos en el carro ni por un minuto solos.yo tengo tres y los cuido mas que mi propia vida ..mi mas sentido pesame a la familia lopezhttp://www.gatchina.biz/item/113.htmlhttp://www.gatchina.biz/vektorhttp://www.gatchina.biz/item/113/20.htmlhttp://www.gatchina.biz/juristhttp://www.gatchina.biz/audit

给我留言取消回复