您的位置:首页 > 其它

Hibernat 的SessionFactory的getCurrentSesion()方法详解

2015-04-02 16:33 120 查看
如果在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(CMT)中进行的,此时这个方法会将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,要解决这个问题的话,可以配置多个SessionFactory,将其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{

InitialConte xt=(UserTransaction)new InitialContext().lookup("java:comp/UserTransaction");

tx.begin();

//Do some work on Session bound to transaction

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: