阿宝 Keep Walking......


JUST DO IT, DO YOUR BEST ! -- 勿在浮沙筑高台

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  49 Posts :: 6 Stories :: 26 Comments :: 0 Trackbacks

如果在hibernate.cfg.xml中配置了
  <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property> 
  <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
  <property
name="hibernate.current_session_context_class">jta</property>
这个配置的意思是当前对于这个SessionFactory(org.hibernate.transaction.CMTTransactionFactory的实例)来说,方法getCurrentSessiong()这个操作都应该在Container Manager Transaction中进行的,此时这个方法会将Session和Transaction进行绑定,对于应用来说则只需调用getCurrentSession就可以了,无需关心Session的Commit和Close.但是如果不是在一个Container Manager Transaction的Bean中调用SessionFactory.getCurrentSession(),则会抛出如下"org.hibernate.HibernateException: Unable to locate current JTA transaction"
,我想是因为容器没有为当前的Bean开始事务,所以这个方法无法绑定Session到当前的JTA transaction中去.

所以在配置前要想清楚是不是所有的操作都是在CMT中进行的,如果不是的话,不能够进行这样的操作.在一个应用中,往往有多个senarior,有的是通过CMT的session bean来调用,而有的则是通过Service直接调用DAO,要解决这个问题的话,可以配置多个SessiongFactory,将其Bind到容器的JNDI树中去.在调用的时候根据当前的Senaior来取不同的SessionFactory.

例如可以为所有通过的CMT管理的Bean作上述配置,对于BMT管理的配置如下:
  <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property> 
  <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
  <property
name="hibernate.current_session_context_class">jta</property>
使用的代码如下:
//BMTidiomwithgetCurrentSession()
try{
 UserTransactiontx=(UserTransaction)newInitialContext()
 .lookup("java:comp/UserTransaction");
 tx.begin();
 //DosomeworkonSessionboundtotransaction
 factory.getCurrentSession().load(...);
 factory.getCurrentSession().persist(...);
 tx.commit();
}
catch(RuntimeExceptione){
 tx.rollback();
 throwe;//ordisplayerrormessage
}

其实这里与CMT不同的就是要手动开始一个Transaction,SessionFactory检查这个Transaction是否是Begin,然后绑定一个Session到这个Transaction上去.

如果是在非托管的环境的应用的话,用JDBCTransactionFactory就可以了,另外对于hibernate.current_session_context_class可以设置为Thread,通过Session.getCurrentSesion()这个方法,让每个Thread公用一个session,同样你也无须关心Sesion的打开和关闭.
//Non-managedenvironmentidiomwithgetCurrentSession()
try{
 factory.getCurrentSession().beginTransaction();
 //dosomework
 ...
 factory.getCurrentSession().getTransaction().commit();
}
catch(RuntimeExceptione){
 factory.getCurrentSession().getTransaction().rollback();
 throwe;//ordisplayerrormessage
}
注意如果采取这种方式获得Session,即使对查询语句也需要开始事务,否则会抛异常.
org.hibernate.HibernateException: createSQLQuery is not valid without active transaction

如果对于CMT,BMT和非托管环境都要用到的,则不再适合用SessionFactory.getCurrentSession(),而需要用OpenSession,并自己负责事务的提交以及Sesion的Close.

posted on 2006-05-28 01:34 阿宝 阅读(6981) 评论(1)  编辑  收藏

Feedback

# re: Hibernat 的SessionFactory的getCurrentSesion()方法详解 2006-11-17 03:01 吴克
JTA和CMT有什么区别吗?我感觉没什么区别吗?一个是使用,一个是声名,jdbc倒是和他们的区别很大!!  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: