请注意,在hibernate中SessionFactory是被设计成线程安全(Thread-safe)的,遗憾的是,Session却线程不安全。

这就意味着:有可能多个线程共享并操作同一个Session从而很容易使数据混乱。

解决的办法如下:(其实hibernate的文档中早已经提过了)

新建HibernateUtil类:

  1. import org.apache.commons.logging.Log;
  2. import org.apache.commons.logging.LogFactory;
  3. import org.hibernate.*;
  4. import org.hibernate.cfg.*;

  5. public class HibernateUtil {
  6.     private static Log log = LogFactory.getLog(HibernateUtil.class);
  7.     private static final SessionFactory sessionFactory;

  8.     static {
  9.         try {
  10.             // Create the SessionFactory
  11.             sessionFactory = new Configuration().configure()
  12.                                                 .buildSessionFactory();
  13.         } catch (Throwable ex) {
  14.             // Make sure you log the exception, as it might be swallowed
  15.             log.error("Initial SessionFactory creation failed.", ex);
  16.             throw new ExceptionInInitializerError(ex);
  17.         }
  18.     }

  19.     public static final ThreadLocal session = new ThreadLocal();

  20.     public static Session currentSession() {
  21.         Session s = (Session) session.get();

  22.         // Open a new Session, if this Thread has none yet
  23.         if (s == null) {
  24.             s = sessionFactory.openSession();
  25.             session.set(s);
  26.         }

  27.         return s;
  28.     }

  29.     public static void closeSession() {
  30.         Session s = (Session) session.get();

  31.         if (s != null) {
  32.             s.close();
  33.         }

  34.         session.set(null);
  35.     }
  36. }

这样,在程序中可这样调用:

  1. Session session = HibernateUtil.currentSession();
  2. User user = (User) session.load(User.class, new Integer(1));
  3. System.out.println(user.getName());
  4. HibernateUtil.closeSession();

在web应用中,可以借由Filter来进行session管理。在需要session的时候开启session,在request结束之后关闭session。

HibernateSessionUtil.java

  1. import java.io.Serializable;

  2. import net.sf.hibernate.HibernateException;
  3. import net.sf.hibernate.Session;
  4. import net.sf.hibernate.SessionFactory;
  5. import net.sf.hibernate.Transaction;

  6. public class HibernateSessionUtil implements Serializable
  7. {
  8.     public static final ThreadLocal tLocalsess = new ThreadLocal();

  9.     public static final ThreadLocal tLocaltx = new ThreadLocal();

  10.     /*
  11.      * getting the thread-safe session for using
  12.      */
  13.     public static Session currentSession(){
  14.         Session session = (Session) tLocalsess.get();

  15.         //open a new one, if none can be found.
  16.         try{
  17.             if (session == null){
  18.                 session = openSession();
  19.                 tLocalsess.set(session);
  20.             }
  21.         }catch (HibernateException e){
  22.             throw new InfrastructureException(e);
  23.         }
  24.         return session;
  25.     }

  26.     /*
  27.      * closing the thread-safe session
  28.      */
  29.     public static void closeSession(){

  30.         Session session = (Session) tLocalsess.get();
  31.         tLocalsess.set(null);
  32.         try{
  33.             if (session != null && session.isOpen()){
  34.                 session.close();
  35.             }

  36.         }catch (HibernateException e){
  37.             throw new InfrastructureException(e);
  38.         }
  39.     }

  40.     /*
  41.      * begin the transaction
  42.      */
  43.     public static void beginTransaction(){
  44.         Transaction tx = (Transaction) tLocaltx.get();
  45.         try{
  46.             if (tx == null){
  47.                 tx = currentSession().beginTransaction();
  48.                 tLocaltx.set(tx);
  49.             }
  50.         }catch (HibernateException e){
  51.             throw new InfrastructureException(e);
  52.         }
  53.     }

  54.     /*
  55.      * close the transaction
  56.      */
  57.     public static void commitTransaction(){
  58.         Transaction tx = (Transaction) tLocaltx.get();
  59.         try{
  60.             if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
  61.                 tx.commit();
  62.             tLocaltx.set(null);
  63.         }catch (HibernateException e){
  64.             throw new InfrastructureException(e);
  65.         }
  66.     }

  67.     /*
  68.      * for rollbacking
  69.      */
  70.     public static void rollbackTransaction(){
  71.         Transaction tx = (Transaction) tLocaltx.get();
  72.         try{
  73.             tLocaltx.set(null);
  74.             if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
  75.                 tx.rollback();
  76.             }
  77.         }catch (HibernateException e){
  78.             throw new InfrastructureException(e);
  79.         }
  80.     }

  81.     private static Session openSession() throws HibernateException{
  82.         return getSessionFactory().openSession();
  83.     }

  84.     private static SessionFactory getSessionFactory() throws HibernateException{
  85.         return SingletonSessionFactory.getInstance();
  86.     }
  87. }

filter中则:

  1. public class HibernateSessionCloser implements Filter{

  2.     protected FilterConfig filterConfig = null;

  3.     public void init(FilterConfig filterConfig)throws ServletException{
  4.     this.filterConfig = filterConfig;
  5.     }
  6.     
  7.     public void destroy(){
  8.         this.filterConfig = null;
  9.     }    

  10.     public void doFilter(ServletRequest request, ServletResponse response,
  11.                          FilterChain chain)
  12.     throws IOException, ServletException {
  13.         try{
  14.             chain.doFilter(request, response);
  15.         }
  16.         finally{
  17.             try{
  18.                 HibernateSessionUtil.commitTransaction();
  19.             }catch (InfrastructureException e){
  20.                 HibernateSessionUtil.rollbackTransaction();
  21.             }finally{
  22.                 HibernateSessionUtil.closeSession();
  23.             }   
  24.         }

  25.     }
  26. }

然后在操作数据库前加上

HibernateSessionUtil.beginTransaction();
HibernateSessionUtil.currentSession();//取得Session



ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程