session问题解决

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 {
    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);

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

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 class = "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" inverse = "true" table = "answer" lazy="false" >
        < key >
          < column name = "qid" />
        </ key >
        < one-to-many class = "dj.fantlam.myssh.vo.Answer" />
</ set >


今天我又发现了一个问题,原来之前的解决方案是多余的。我就是觉得很奇怪,前段日子就是怎么测都是 session 关闭了,真的很莫名其妙。实际上 OpenSessionInViewFilter 这个配置就是解决在 web session 的问题,而之前我配了之后不起作用,现在想想原因应该是 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 种方法都是一样的, ContextLoaderListener ContextLoaderServlet 底层都依赖 ContextLoader ,因此两者效果几乎没有什么区别。在 Servlet2.3 标准中才出现 ContextLoaderListener ,它比 ContextLoaderServlet 会优先加载。

现在我得出的结论是之前是 OpenSessionInViewFilter 不起作用,如果我不把 plugin
去掉的话问题依旧。经过测试,我不加 plugin问题就没了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值