使用Hibernate時,大家一般都記住了配置基本的那些選項,比如方言,緩存等,但是有一項配置卻很容易忘掉,這就是連接釋放模式:hibernate.connection.release_mode,可有三個選擇,after_statement/after_transaction/on_close,javadoc中可以看出它們的用處,這裡不再講,注意的一點是,如果不配置的話默認是on_close,那麼如果沒有顯示的去調用session.close或其它關閉連接的方法的話,這個連接是不會被關閉的!在用到連接池的時候,這就更體現出問題了:池中的連接會一直存在著而不會被關閉和回收!
從log4j打印出來的日志也可以看出來,如果是on_close模式,則:
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
具體的一些細節可以看看hibernate的源代碼,涉及到的兩個類為:
org.hibernate.ConnectionReleaseMode
org.hibernate.jdbc.ConnectionManager
最後,貼一下配置的代碼:
<prop key="hibernate.connection.release_mode">after_transaction</prop>
=========================================
转载于 :http://blog.myspace.cn/e/404057125.htm
最近在做项目时遇到一个问题,程序框架用的是Spring + Hibernate + Struts,当对数据库进行操作时,程序在运行几次之后,就会再无反应,浏览器的进度条也停在中间不走了,看控制台也并没有报任何异常,最后在日志中找出了点东东,还算有用,日志输出下面这句后就停止了,程序就执行到此了。
[org.hibernate.jdbc.ConnectionManager]-[DEBUG] opening JDBC connection
明显是数据库连接问题,向上翻看日志,发现数据库连接没有释放。源文件如下:
public class OrdersDao extends HibernateDaoSupport { //方式一
/*
* 查询订单
*/
public List<Orders> getAllOrders() {
String hql = "From Orders ";
Query query = super.getSession().createQuery(hql);
return query.list();
}
}
后来上网查了资料,说是session没有关闭,也就是连接没有释放,所以,我就改成了如下代码:
public class OrdersDao extends HibernateDaoSupport {
/*
* 查询订单
*/
public List<Orders> getAllOrders() {
Session session = null;
try {
session = super.getSession();
String hql = "From Orders ";
Query query = session.createQuery(hql);
return query.list();
} catch (Exception e) {
e.printStackTrace();
return null;
}finally{
session.clear();
session.close();
}
}
问题解决了。
不过,在网上查到的资料中,有的人同样是这样关闭了session,可问题却依旧存在,在随后我同样这样修改另一个项目中的源码时,运行后问题也是依旧存在,没有解决,我就依次查看日志,发现因为我在项目用了Hibernate的关联映射,在查询加载数据时对其它实体对象也进地了加载,而没有全部修改,这时我把其它所有关联的查询的session都关闭,再次部署运行后,问题就不复存在了。
这种问题还有一种解决方式就是用 Spring 方式的编码进行实现。代码如下:
public class OrdersDao extends HibernateDaoSupport { //方式二
/*
* 查询订单
*/
public List<Orders> getAllOrders() {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException,SQLException {
Query query = session.createQuery("From Orders ");
List list = query.list();
return list;
}
}
);
}
采用这样的编码,问题也能解决。
这就要说一下方式一和方式二这两种方法的区别了。这两种方式的区别就是对Session的控制,方式一中写法要自己控制Session的释放,而方式二的写法刚由Spring的模板类控制Session,把Session的控制问题全抛给模板处理了。这样看来,要在Spring下做开发,方式二的方法会好些,但是,方式二的写法有些怪异,并且麻烦,所有我个人还是喜欢方式一中 的写法,简洁明朗。
如果有人喜欢Spring风格的编码,我在网上查资料时发现了一份别人打包好的Spring风格编码,简化了这种编码方式。代码如下:
Spring的处理方式
Spring用回调HibernateCallBack方法实现持久层一些功能,当这些功能不能满足需求时,我们也可以自已来重写HibernateCallBack,例:
package com.notepad.comm;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
public class HQLCallBackUtil implements HibernateCallback {
private String hql;
public HQLCallBackUtil(){
}
public HQLCallBackUtil(String hql){
this.hql=hql;
}
public String getHql() {
return hql;
}
public void setHql(String hql) {
this.hql = hql;
}
public Object doInHibernate(Session s) throws HibernateException,
SQLException {
if (hql == null || hql.equals("")) {
throw new HibernateException("Can't execute NULL hql!");
}
return s.createQuery(hql).list();
}
}
然后可以通过如下代码进行调用
public class UsersDAO extends HibernateDaoSupport {
......
public List getUsers() {
HQLCallBackUtil callBack=new HQLCallBackUtil();
callBack.setHql("From Users AS user ORDER BY user.username DESC");
return this.getHibernateTemplate().executeFind(callBack);
}
......
}
这样是不是感觉简单很多呢!