论坛首页 Java企业应用论坛

再论 ThreadLocal

浏览 5890 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-01-09  
在此间我经常看见一些帖子论述到hibernate 和 struts 结合使用的时候都建议使用ThradLocal:
public static final ThreadLocal session = new ThreadLocal();;

但是我个人觉得并无必要。
理由如下:
首先虽然servlet是多线程的,但是一般调用hibernate访问数据库都在BO /dao这一层,一般来说这一层都会在action 的 excute 方法中调用,所以拿到的session再excute方法中是有自己堆栈的,所以不会有多线程的问题,那么在sessionFactory.openSession();(这里假设sessionFactory已经建立)在openSession的过程中从连接池拿到connection的过程中肯定排他的,所以说不会产生两个对象拿到同一个session的问题.那就没有必要用到
ThreadLocal不知道我的说法对不对,请大家指点
   发表时间:2004-01-09  
ThreadLocal和多线程并发没有什么关系。ThreadLocal模式是为了解决单线程内的跨类跨方法调用的,有点AOP的味道。前面已经讲了很多了,还是搜索一下吧。
0 请登录后投票
   发表时间:2004-01-09  
多谢,一句话点醒梦中人。
但是,我还有一个问题:一般情况下应该对connection 尽可能迟的取得,尽早的释放,以获得最高的并发,如果放到ThreadLocal里面到最后filter里面再释放,显然多占用的connection的时间,使统的并发降低。另外由于连接池的使用在重新get connection 也不会使用多少资源。至于事务的控制我觉得放到BO
我认为Po放数据作为和hbm.xml结合作为数据字典用,dao通过冬眠来访问数据库,然后由bo来根据具体业务组织事务(看了这里很多讨论我认为有bo来组织事务显然比用dao来组织事务更灵活,应为对数据库的访问是否编在一个事物里显然改由业务决定!)这样对 bo来说访问的就像是对象数据库一样了!

不知道大家是怎么想的?
0 请登录后投票
   发表时间:2004-01-09  
放在bo里面会使你的bo通用性下降。
0 请登录后投票
   发表时间:2004-01-09  
引用
一般情况下应该对connection 尽可能迟的取得,尽早的释放,以获得最高的并发,如果放到ThreadLocal里面到最后filter里面再释放,显然多占用的connection的时间,使统的并发降低


不会的。除非你访问一个页面要好几十秒到几分钟。

引用
另外由于连接池的使用在重新get connection 也不会使用多少资源


在一次调用过程中多次申请归还连接对象,确实不会对性能有太大损失。但是对于编程模型来说,在没有容器管理事务的情况下,你没有办法进行跨类跨方法的事务管理。

引用
至于事务的控制我觉得放到BO

事务放在哪一层处理,哪一层就不具备跨方法调用的能力。假设你的BO1里面有事务处理,BO2也有事务处理。然后你的BO3要调用BO1的某方法,和BO2的某方法,那么一旦你在BO3里面启动事务,然后调用BO1,就会报错,因为事务是扁平的,不能嵌套的。这样的结果会造成在实际项目中,你的BO根本就写不下去了。

其实在很久以前,在论坛开张的时候,我就在精华区发贴详细分析过这个问题了。简单的来说,如果你不采用容器管理事务,那么就用ThreadLocal + Filter(在非Web应用中,在程序执行完毕前释放连接),如果你采用容器管理事务,那么就不需要ThreadLocal,用完就关。
0 请登录后投票
   发表时间:2004-01-09  
很高兴了解了一种跨方法调用session的方法。多谢robbin!
但是还有一个问题:如何组织一个事物:也就是说在什么地方commit,假设有这样几个BO方法:BO1,BO2,BO3,有时候BO1本身作为一个事物,有时候BO3包含BO1所作的事情并且组织成一个事物,那么应该在哪里commit?如果在BO1里面commit,显然BO3调用BO1的时候就不满足事务的原子性要求(因为在BO1里commit了)这个时候虽然实现了session(connection)的跨方法调用却没有解决更本问题,事务的组织。
   如果都在filter里面commit,呢么可能这个事务太长,远远的超出了本来需要的长度,会严重影响数据的性能(特别是在压力测试的时候!)。
  我们现在都是在BO里面通过调用DAO来获得重用

	public UserPO updateUserInformation(
		int id,
		String newpassword,
		String renewpassword,
		String newusername,
		String newemail,
		List roleidlist,
		int valid);
		throws LogicException, DAOException {
		ITxMgr tx = null;
		UserDAO userdao = new UserDAO();;
		UserPO user = null;
		RoleDAO roledao = new RoleDAO();;
		RolePO role = null;
		UserRoleDAO userroledao = new UserRoleDAO();;
		

		if (newpassword == null); {
			throw new LogicException(
				MessageArrayList.PASSWORD_SHOULD_NOT_BE_NULL);;
		} else {
			if (!newpassword.equals(renewpassword);); {
				throw new LogicException(
					MessageArrayList.REPASSWORD_NOT_EQUAL_PASSWORD);;
			}
		}
		try {
			tx =
				HibernateTxMgr.beginTrans(
					"Update the information of user...");;
			userdao.joinTx(tx);;
			user = userdao.getUserByUserID(id);;
			if(user==null);{
				throw new LogicException(MessageArrayList.USER_NOT_EXIST);;
			}
			userdao.updateUserInformation(
				user,
				newpassword,
				newusername,
				newemail,
				valid);;
			userroledao.joinTx(tx);;
			userroledao.deleteUserRoleByUserID(user.getId(););;
			roledao.joinTx(tx);;
			for(int i=0;i<roleidlist.size();;i++);{
				role = roledao.getRoleByRoleID(((Integer);roleidlist.get(i););.intValue(););;
				if(role!=null);{
					userroledao.addNewUserRole(user,role);;
				} else {
					tx.rollback();;
					throw new LogicException(MessageArrayList.ROLE_NOT_EXIST);;
				}
			}
		} catch (TxMgrException e); {
			tx.rollback();;
			logger.fatal(e.toString(););;
			throw new DAOException(e);;
		} catch (HibernateException e); {
			tx.rollback();;
			logger.fatal(e.toString(););;
			throw new DAOException(e);;
		} finally {
			try {
				tx.endTrans();;
			} catch (TxMgrException te); {
				logger.fatal(te.toString(););;
				throw new DAOException(te);;
			}
		}
		return user;
	}

这里tx.endTrans();执行了COMMIT。
如果改用ThreadLocal 在COMMIT的方面如果有好的办法的话,希望ROBBIN能介绍一下
0 请登录后投票
   发表时间:2004-01-09  
总要有一个类来控制事务边界把,ThreadLocal只解决了session阿
0 请登录后投票
   发表时间:2004-01-09  
用ThreadLocal + Filter 只解决了一种通用的粗粒度的控制方法. 你可以用事务容器的方式, 不同的组件设置成不同的事务类型, support, required等.
0 请登录后投票
论坛首页 Java企业应用版

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