论坛首页 Java企业应用论坛

关于用Threadlocal来管理跨类的事务的疑惑。

浏览 4303 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-02-29  
现在有用Threadlocal来管理跨类的事务,其原理就是将事务与线程绑定(通过在一个线程中使用一个连接实现),这样在一个线程中的操作就在一个事务中了如:
TransactionManager.beginTransaction();
f1();
f2();
TransactionManager.closeTransaction();
其中
TransactionManager.beginTransaction()方法是将线程与数据库连接绑定,并将连接的自动提交设置为false;
TransactionManager.closeTransaction()方法是将线程与数据库连接绑定撤销,并提交连接:conn.commit();

这样f1()与f2()就在一个事务中调用了。这的确很方便。

这在正常情况下是没有问题的,但是当f1()或f2()因为业务逻辑出现异常时,TransactionManager.closeTransaction()有可能没有调用,线程与数据库连接绑定也就没有撤销。这在一般c/s程序中可能没有问题,但当在web应用中时,是不是会有问题了?因为在web server中存在线程池,当上一个线程处理完后可能又会服务于新的请求。但当上一个请求中因异常没有调用TransactionManager.closeTransaction(),此时新的请求将用到上一请求的数据库连接,这样就有可能这次的操作于上次操作在一个事务中了,这就不对了吧?请问各位大侠对此有何见解?
   发表时间:2004-02-29  
try{
}catch(...){
}finally{
}
0 请登录后投票
   发表时间:2004-02-29  
to yehs220:

实际此问题的关键在于对每一个以beginTransaction()开始的调用,不管如何都必须有且只有一个closeTransaction()与之对应。但这在实际操作的时候可能并不容易完全能做到。特别是在逻辑很复杂时或编程时没有注意,都存在问题如:
void fall(){
TransactionManager.beginTransaction();
try{
  if(..){
     TransactionManager.closeTransaction();  //1
     return;
  }
  f1();
  f2();
  try{
    f3();
  }
  catch(MyException e){
     throw MyException();
  }
        }
catch(MyException e){
          TransactionManager.closeTransaction();  //2
  throw MyException ();
}catch(Exception e){
  TransactionManager.closeTransaction();  //3
  throw Exception ();
}
       TransactionManager.closeTransaction();  //4
}
如果1、2、3处没有调用TransactionManager.closeTransaction(),在正常情况下是不能测试出来的。但其实这是存在着很大的隐患,类似于jdbc中不关闭连接的情况,但隐蔽性更强。那如何才能避免这种情况了?
0 请登录后投票
   发表时间:2004-03-01  
没看懂你的意思。
这样不就可以了,你也可以把事务处理用模板模式封装一下,这样更容易写也不容易出错。或者你可以用aop来处理事务好了...
Session session=...;
Transaction tx=null;
try{
  tx=session.beginTransaction();;
  f1();;
  f2();;
  tx.commit();;
}catch(Exception e);{
  if(tx!=null);{
    tx.rollback();;
  }
  throw e;
}
0 请登录后投票
   发表时间:2004-03-01  
使用ThreadLocal封装db connection后数据库连接的最大数==最大线程数???

也就是说,在weblogic里面,分配给http的最大线程数为50
那么db connection最多也就使用50个连接对吗???
0 请登录后投票
   发表时间:2004-03-01  
按照我的理解,应该不会。连接池的实现一般有两个集合,一个存放已经释放的可用连接,一个存放正在使用的连接,如果不做显示的释放,连接的状态不会发生变化,后续线程是不会使用到这个连接的。
0 请登录后投票
论坛首页 Java企业应用版

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