论坛首页 Java企业应用论坛

Hibernate文档上的这段话如何解释?

浏览 8788 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2003-11-24  
In a web-based application, a servlet filter can be used to close the Session only at the very end of a user request, once the rendering of the view is complete. Of course, this places heavy demands upon the correctness of the exception handling of your application infrastructure. It is vitally important that the Session is closed and the transaction ended before returning to the user, even when an exception occurs during rendering of the view. The servlet filter has to be able to access the Session for this approach. We recommend that a ThreadLocal variable be used to hold the current Session.

他就是说用ThreadLocal可以解决lazy="false"的bug. 谁有个用ThreadLocal的具体的例子来说明上面这段话?
   发表时间:2003-11-24  
随便写了一下,没有严格的Test,参考一下吧

/*
 * Created on 2003-11-16
 *
 */

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.tool.hbm2ddl.SchemaExport;

/**
 * 
 * 获取Session连接工厂类
 * 
 * @author Robbin Fan
 *
 */
public class ReportSession {
	
	
	private static final ThreadLocal sessionThread = new ThreadLocal();;
	
	private static final ThreadLocal transactionThread = new ThreadLocal();;
	
	/**
	 * 获取当前线程使用的Session
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session currentSession(); throws HibernateException {
		Session s = (Session); sessionThread.get();;		
		if (s == null); {
			SessionFactory sf = new Configuration();.configure();.buildSessionFactory();;
			s = sf.openSession();;
			sessionThread.set(s);;		
		}
		return s;
	}
	
	/**
	 * 启动或者加入当前Session的Transaction
	 * 
	 * @return Transaction
	 * @throws HibernateException
	 */
	public static Transaction currentTransaction(); throws HibernateException {
		Transaction tx = (Transaction); transactionThread.get();;
		if (tx == null); {
			tx = currentSession();.beginTransaction();;
			transactionThread.set(tx);;
		}
		return tx;
	}
	
	/**
	 * 提交当前Session的Transaction
	 * 
	 * @throws HibernateException
	 */
	public static void commitTransaction(); throws HibernateException {
		Transaction tx = (Transaction); transactionThread.get();;
		transactionThread.set(null);;
		if (tx != null); tx.commit();;
	}
	
	/**
	 * 关闭当前线程使用的Session
	 * 
	 * @throws HibernateException
	 */
	public static void closeSession(); throws HibernateException {
		Session s = (Session); sessionThread.get();;
		sessionThread.set(null);;
		if (s != null); s.close();;
	}

	/**
	 * 根据映射文件和持久对象生成数据库DDL,生成文件为create_table.sql
	 * 
	 * @param args 参数
	 */
	public static void main(String[] args); {
		try {
			Configuration cfg = new Configuration();.configure();;
			SchemaExport se = new SchemaExport(cfg);;
			se.setOutputFile("create_table.sql");;
			se.create(true,true);;
		} catch (HibernateException e); {			
			e.printStackTrace();;
		}
		
	}
}
0 请登录后投票
   发表时间:2003-11-24  
在程序里面使用Hibernate这样来获得Session和Transaction,不用提交Transaction和关闭Session,如果是查询,那么不需要启动Transaction。

try {
    Session s = ReportSession.currentSession();;
     ReportSession.currentTransaction();;

     ...
     s.save(...);;
     ...
     s.flush();;

} catch (HibernateException e); {
    e.printStackTrace();;
}


在ServletFilter的doFilter方法里面写如下代码出来Transaction和关闭Session:

ReportSession.commitTransaction();;
ReportSession.closeSession();;
0 请登录后投票
   发表时间:2003-11-24  
robbin 写道

	/**
	 * 获取当前线程使用的Session
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session currentSession(); throws HibernateException {
		Session s = (Session); sessionThread.get();;		
		if (s == null); {
			SessionFactory sf = new Configuration();.configure();.buildSessionFactory();;
			s = sf.openSession();;
			sessionThread.set(s);;		
		}
		return s;
	}
怀疑这段代码有问题:会不会生成多个 sf 呢? 明天测试一下。
0 请登录后投票
   发表时间:2003-11-24  
多谢,我好好理解一下
0 请登录后投票
   发表时间:2003-11-24  
tomcat 写道
robbin 写道

	/**
	 * 获取当前线程使用的Session
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session currentSession(); throws HibernateException {
		Session s = (Session); sessionThread.get();;		
		if (s == null); {
			SessionFactory sf = new Configuration();.configure();.buildSessionFactory();;
			s = sf.openSession();;
			sessionThread.set(s);;		
		}
		return s;
	}


怀疑这段代码有问题:会不会生成多个 sf 呢?
明天测试一下。


有可能会,如果第一次请求的时候,就有很多线程并发,就会产生好几个sf,不过即使产生好几个sf也无关紧要,对程序也没有什么影响。实际上只要初始sf生成了,以后多个线程并发就不会产生sf了,只有一个sf。所以这种情况只会出现在应用软件第一次被访问的时候,并且是第一次被访问就有多线程并发才会出现,因此出现的几率很小,并且就算出现了,对整个软件来说,也没有什么影响。因此这个问题可以不用去管它的。

如果你严格限制只产生一sf,那么可以给这个方法进行synchronized,那么就会保证永远产生一个sf,但是代价很高,多线程实际上不能够真正的并发执行了,会影响多线程并发的时候Session获得的性能。
0 请登录后投票
   发表时间:2003-11-24  
多谢,我好好理解一下
0 请登录后投票
   发表时间:2003-11-27  
robbin 写道
tomcat 写道
robbin 写道

	/**
	 * 获取当前线程使用的Session
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session currentSession(); throws HibernateException {
		Session s = (Session); sessionThread.get();;		
		if (s == null); {
			SessionFactory sf = new Configuration();.configure();.buildSessionFactory();;
			s = sf.openSession();;
			sessionThread.set(s);;		
		}
		return s;
	}


怀疑这段代码有问题:会不会生成多个 sf 呢?
明天测试一下。


有可能会,如果第一次请求的时候,就有很多线程并发,就会产生好几个sf,不过即使产生好几个sf也无关紧要,对程序也没有什么影响。实际上只要初始sf生成了,以后多个线程并发就不会产生sf了,只有一个sf。所以这种情况只会出现在应用软件第一次被访问的时候,并且是第一次被访问就有多线程并发才会出现,因此出现的几率很小,并且就算出现了,对整个软件来说,也没有什么影响。因此这个问题可以不用去管它的。

如果你严格限制只产生一sf,那么可以给这个方法进行synchronized,那么就会保证永远产生一个sf,但是代价很高,多线程实际上不能够真正的并发执行了,会影响多线程并发的时候Session获得的性能。


robbin,你在上面说“有很多线程并发,就会产生好几个sf,不过即使产生好几个sf也无关紧要,对程序也没有什么影响”
那这些产生出来的多余的SF,在什么时候被关闭和释放呢?
0 请登录后投票
   发表时间:2003-11-27  
是不是可以考虑用threadlocal做一个stack放sf, 或者Double check处理一下.
0 请登录后投票
   发表时间:2003-11-27  
sf不打开数据库,不占用数据库资源,不需要显式释放。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics