精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2004-04-20
但在Web应用中,我发现在filter里面close连接无疑是最合适的 如果在其他地方close 连接,后面的调用得到的connection就是isColsed,无法再使用,如果再open一次,就不是以前的连接了,就无法保证事务了 并且用ThreadLocal实现的也只是粗粒度的事务,尤其是在B/S应用中 ThreadLocal,鸡肋? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-04-20
ejb中的container managered transaction用的也是类似ThreadLocal或者就是ThreadLocal的技术,ejb也是鸡肋
还是好好看看ThreadLocal到底是个什么东东吧? |
|
返回顶楼 | |
发表时间:2004-04-20
为什么说threadlocal是鸡肋呢?关键是看你如何设计吧。我觉得使用threadlocal和使用filter在web 里面效果是一样的,而threadlocal更通用一点,可以用在非web的场合。
|
|
返回顶楼 | |
发表时间:2004-04-20
sorry
我想我已经理解ThreadLocal是什么了 直接说ThreadLocal是鸡肋的确不对 现在把问题定位在“在B/S应用中用ThreadLocal管理Connection是否可取”上 我觉得这并不是一个很好的方法,原因同上 |
|
返回顶楼 | |
发表时间:2004-04-20
wes109 写道 用ThreadLocal可以解决一定的事务问题
但在Web应用中,我发现在filter里面close连接无疑是最合适的 如果在其他地方close 连接,后面的调用得到的connection就是isColsed,无法再使用,如果再open一次,就不是以前的连接了,就无法保证事务了 并且用ThreadLocal实现的也只是粗粒度的事务,尤其是在B/S应用中 ThreadLocal,鸡肋? 你为什么要在其他地方close呢? 事务的scope是在Session的scope里面的,你都已经close了Session了,当然不会在一个事务里面了。 你怎么知道是粗粒度,那是你不会用,你就不会把Transaction也放到ThreadLocal里面,实现细粒度的事务控制吗?贴段代码给你参考: /* * 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中,你直接: Session session = HibernateSession.currentSession();; HibernateSession.currentTransaction();; ..... session.flush();; 事务的提交和Session的close都在Filter里面完成,Filter里面代码如下: 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需要一个细颗粒度的事务的话,那么你就 Session session = HibernateSession.currentSession();; HibernateSession.currentTransaction();; ..... session.flush();; HibernateSession.commitTransaction();; 这样就可以实现一个细颗粒度的事务,而且在该线程执行序列中,接下去的另一个方法调用也是类似: Session session = HibernateSession.currentSession();; HibernateSession.currentTransaction();; ..... session.flush();; 这样的代码,而HibernateSession.currentTransaction();会自己检查当前是否已经启动事务,如果发现没有启动事务,那么就会新启动一个事务的。 因此,如果你需要细颗粒度的事务的话,就在你方法里面 HibernateSession.commitTransaction();;如果你不需要细颗粒度事务的话,就不写这句代码就OK了,最后Filter会提交。 |
|
返回顶楼 | |
发表时间:2004-04-20
妙!!!
|
|
返回顶楼 | |
发表时间:2004-04-20
前天看hibernate的source,一直没弄明白session和transaction是怎么关联的
Session.java有30多K,看得头晕:( 其实我想参照hibernate的代码,实现自己的Connection和Transaction管理,呵呵 可能没有必要,只是想做一个尝试,了解一个实现机制 偶是菜鸟,见笑了 robbin能写一些hibernate源码剖析的文章就好了。。。 |
|
返回顶楼 | |
发表时间:2004-04-20
你太客气了,有空再说吧,最近忙死了。
|
|
返回顶楼 | |
发表时间:2004-04-20
突然想到:
在filter里面操作session和transaction是否与各层分离的思想不符? |
|
返回顶楼 | |
发表时间:2004-04-21
wes109 写道 突然想到:
在filter里面操作session和transaction是否与各层分离的思想不符? 你不一定非要在filter里面操作不可,准确的来说,只不过是需要在一个层的边界来操作,例如你如果分离Web层和业务层的话,你可以在业务层的Session Facade来完成这个工作,前提是你要保证在每个方法最后都close一下Session。 |
|
返回顶楼 | |