如果在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()這個操作都應(yīng)該在Container Manager Transaction中進行的,此時這個方法會將Session和Transaction進行綁定,對于應(yīng)用來說則只需調(diào)用getCurrentSession就可以了,無需關(guān)心Session的Commit和Close.但是如果不是在一個Container Manager Transaction的Bean中調(diào)用SessionFactory.getCurrentSession(),則會拋出如下"org.hibernate.HibernateException: Unable to locate current JTA transaction"
,我想是因為容器沒有為當前的Bean開始事務(wù),所以這個方法無法綁定Session到當前的JTA transaction中去.
所以在配置前要想清楚是不是所有的操作都是在CMT中進行的,如果不是的話,不能夠進行這樣的操作.在一個應(yīng)用中,往往有多個senarior,有的是通過CMT的session bean來調(diào)用,而有的則是通過Service直接調(diào)用DAO,要解決這個問題的話,可以配置多個SessiongFactory,將其Bind到容器的JNDI樹中去.在調(diào)用的時候根據(jù)當前的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上去.
如果是在非托管的環(huán)境的應(yīng)用的話,用JDBCTransactionFactory就可以了,另外對于hibernate.current_session_context_class可以設(shè)置為Thread,通過Session.getCurrentSesion()這個方法,讓每個Thread公用一個session,同樣你也無須關(guān)心Sesion的打開和關(guān)閉.
//Non-managedenvironmentidiomwithgetCurrentSession()
try{
?factory.getCurrentSession().beginTransaction();
?//dosomework
?...
?factory.getCurrentSession().getTransaction().commit();
}
catch(RuntimeExceptione){
?factory.getCurrentSession().getTransaction().rollback();
?throwe;//ordisplayerrormessage
}
注意如果采取這種方式獲得Session,即使對查詢語句也需要開始事務(wù),否則會拋異常.
org.hibernate.HibernateException: createSQLQuery is not valid without active transaction
如果對于CMT,BMT和非托管環(huán)境都要用到的,則不再適合用SessionFactory.getCurrentSession(),而需要用OpenSession,并自己負責事務(wù)的提交以及Sesion的Close.