http://forum.javaeye.com/viewtopic.php?t=4588&highlight=threadlocal
你為什么要在其他地方close呢?
事務的scope是在Session的scope里面的,你都已經close了Session了,當然不會在一個事務里面了。
你怎么知道是粗粒度,那是你不會用,你就不會把Transaction也放到ThreadLocal里面,實現細粒度的事務控制嗎?貼段代碼給你參考:
在你的DAOImpl中,你直接:
事務的提交和Session的close都在Filter里面完成,Filter里面代碼如下:
這是粗顆粒度的Transaction。
如果該DAO需要一個細顆粒度的事務的話,那么你就
這樣就可以實現一個細顆粒度的事務,而且在該線程執行序列中,接下去的另一個方法調用也是類似:
這樣的代碼,而HibernateSession.currentTransaction();會自己檢查當前是否已經啟動事務,如果發現沒有啟動事務,那么就會新啟動一個事務的。
因此,如果你需要細顆粒度的事務的話,就在你方法里面
如果你不需要細顆粒度事務的話,就不寫這句代碼就OK了,最后Filter會提交。
wes109 寫道: |
用ThreadLocal可以解決一定的事務問題 但在Web應用中,我發現在filter里面close連接無疑是最合適的 如果在其他地方close 連接,后面的調用得到的connection就是isColsed,無法再使用,如果再open一次,就不是以前的連接了,就無法保證事務了 并且用ThreadLocal實現的也只是粗粒度的事務,尤其是在B/S應用中 ThreadLocal,雞肋? ![]() |
你為什么要在其他地方close呢?
事務的scope是在Session的scope里面的,你都已經close了Session了,當然不會在一個事務里面了。
你怎么知道是粗粒度,那是你不會用,你就不會把Transaction也放到ThreadLocal里面,實現細粒度的事務控制嗎?貼段代碼給你參考:
java代碼: |
/* * Created on 2003-11-16 * */ package com.javaeye.crm; 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 HibernateSession { private static final ThreadLocal sessionThread = new ThreadLocal(); private static final ThreadLocal transactionThread = new ThreadLocal(); private static SessionFactory sf = null; /** * 獲取當前線程使用的Session * * @return Session * @throws HibernateException */ public static Session currentSession() throws HibernateException { Session s = (Session) sessionThread.get(); if (s == null) { if (sf == null) sf = new Configuration().configure().buildSessionFactory(); s = sf.openSession(); sessionThread.set(s); } return s; } /** * 獲取一個新的Session * * @return Session * @throws HibernateException */ public static Session newSession() throws HibernateException { if (sf == null) sf = new Configuration().configure().buildSessionFactory(); Session s = sf.openSession(); 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(); } /** * 回滾當前事務 * * @throws HibernateException */ public static void rollbackTransaction() throws HibernateException { Transaction tx = (Transaction) transactionThread.get(); transactionThread.set(null); if (tx != null) tx.rollback(); } /** * 關閉當前線程使用的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 { String conf = "hibernate.cfg.xml"; if (args.length != 0) conf = args[0]; Configuration cfg = new Configuration().configure("/" + conf); SchemaExport se = new SchemaExport(cfg); //se.setOutputFile("create_table.sql"); se.create(true,true); } catch (HibernateException e) { System.out.println(e.getMessage()); } } } |
在你的DAOImpl中,你直接:
java代碼: |
Session session = HibernateSession.currentSession(); HibernateSession.currentTransaction(); ..... session.flush(); |
事務的提交和Session的close都在Filter里面完成,Filter里面代碼如下:
java代碼: |
try { HibernateSession.commitTransaction(); } catch (HibernateException e) { try { HibernateSession.rollbackTransaction(); } catch (HibernateException e1) { System.out.println(e1.getMessage()); } System.out.println(e.getMessage()); } finally { try { HibernateSession.closeSession(); } catch (HibernateException e) { System.out.println(e.getMessage()); } } |
這是粗顆粒度的Transaction。
如果該DAO需要一個細顆粒度的事務的話,那么你就
java代碼: |
Session session = HibernateSession.currentSession(); HibernateSession.currentTransaction(); ..... session.flush(); HibernateSession.commitTransaction(); |
這樣就可以實現一個細顆粒度的事務,而且在該線程執行序列中,接下去的另一個方法調用也是類似:
java代碼: |
Session session = HibernateSession.currentSession(); HibernateSession.currentTransaction(); ..... session.flush(); |
這樣的代碼,而HibernateSession.currentTransaction();會自己檢查當前是否已經啟動事務,如果發現沒有啟動事務,那么就會新啟動一個事務的。
因此,如果你需要細顆粒度的事務的話,就在你方法里面
java代碼: |
HibernateSession.commitTransaction(); |