摘自: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。
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问题就没了。(若以后有相关问题再继续讨论)
=================无耻分割线,以下是本人的一点小总结=============================
由于我在SSH整合中使用的getSession()方式进行数据库访问
最开始的解决办法是使用Session se=getSession(); se.close()来关闭连接,可是不想却没有任何效果
于是又找到
OpenSessionInViewFilter 的方式还是不能解决,
最后采用的是
Session session = super.getSession();
String hql = "from Item as i";
List l = session.createQuery(hql).list();
releaseSession(session);
问题圆满解决!呵呵