(转)SSH问题总结

来源:互联网 发布:金融专业书籍知乎 编辑:程序博客网 时间:2024/05/19 02:24

本文转载自:http://fantlam.blogbus.com/logs/27339525.html

 

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

方案二:(经测试,此方案比较有效)

设定HibernateTemplate的AllowCreate为True

在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关闭由这个DAO的SessionFactory创建的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问题

 

 

 

网上有这么一种说法

---------------------------------------------------------------------------------------------------

struts跟spring的整合是在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问题就没了。(若以后有相关问题再继续讨论)

原创粉丝点击