--------------------------------------------------------------------------------
代码
package com.censoft.portlets.db.base;
import com.censoft.portlets.db.DbTools;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class HibernateSession {
public static final ThreadLocal sessionContext = new ThreadLocal();
private Session session;
private int level;
public static Session currentSession(String cfgFilePath) throws Exception {
HibernateSession hSession = (HibernateSession)sessionContext.get();
if (hSession == null)
{
hSession = new HibernateSession();
SessionFactory factory = DbTools.getSessionFactory(cfgFilePath);
hSession.session = factory.openSession();
hSession.level = 0;
sessionContext.set( hSession );
}
hSession.level++;
return hSession.session;
}
public static void closeSession() throws Exception {
HibernateSession hSession = (HibernateSession)sessionContext.get();
if (hSession == null)
{
return;
}
hSession.level--;
if (hSession.level <= 0)
{
if (hSession.session != null && hSession.session.isOpen())
{
hSession.session.close();
}
sessionContext.set( null );
}
}
}
在同一个线程里只使用一个session对象
比如我封装的存储和删除的函数分别如下:
<!--存储函数-->
public static boolean merge(Object o) throws HibernateException { /*
* 創建session,存儲對象,最後關閉session
*/
Session s = HibernateSessionFactory.getSession();
Transaction tx = s.beginTransaction();
boolean result = false;
try {
s.merge(o);
tx.commit();
result = true;
} catch (HibernateException he) {
tx.rollback();
throw he;
} finally {
if (s != null) {
s.close();
}
}
return result;
}
<!--删除函数-->
public static boolean deleteObject(String hql) {
try { /*
* 創建session,存儲對象,最後關閉session
*/
Session s = HibernateSessionFactory.getSession();
Transaction tx = s.beginTransaction();
Query query = s.createQuery(hql);
query.executeUpdate();
tx.commit();
s.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
调用的时候先调用存储再调用删除,如果删除过程异常则想要把存储过程回滚,但我已经commit调了。
我的问题是应该如何改造这些函数?
如果你 想在调用 save 在delete 那么你就要把 save 里的事务去掉 这样就可以了
也就是所按调用的顺序去掉事务 保存最后一个事务
这样才能保证 save 和delete 在同一个事务中
先到上述网站上下载JOTM。然后将
jotm.jar 、jotm_jrmp_stubs.jar 、jonas_timer.jar 、carol.jar 、jta-spec1_0_1.jar
jts1_0.jar 、objectweb-datasource.jar 、xapool.jar
这些Jar文件复制到:$TOMCAT_HOME/common/lib/ 目录中。
将JDBC driver 复制到: $TOMCAT_HOME/common/lib/ 目录中。 将文件:carol.properties 复制到:$TOMCAT_HOME/common/classes/ 目录中。 下面,修改 Tomcat 的 Server.xml 配置文件。
[code]
<Resource name="jdbc/dataSrc" auth="Container" type="javax.sql.DataSource"/>
<parameter>
<name>factory</name>
<value>org.objectweb.jndi.DataSourceFactory</value>
..........
</parameter>
<Resource name="UserTransaction" auth="Container"
type="javax.transaction.UserTransaction"/>
<ResourceParams name="UserTransaction">
<parameter>
<name>factory</name>
<value>org.objectweb.jotm.UserTransactionFactory</value>
</parameter>
<parameter>
<name>jotm.timeout</name>
<value>60</value>
</parameter>
</ResourceParams>
[/code]
注意上面的数据库连接池的配置,要用 JOTM 中的 XAPool 。
基本上,我们就配置好了 Tomcat 中的 JOTM。2。Hibernate中的事务配置。(我想这步可以省略,但还没测试。请有心人测试一下。)
在 hibernate.cfg.xml 中 <property name="transaction.factory_class">
net.sf.hibernate.transaction.JTATransactionFactory
</property>
<property name="transaction.manager_lookup_class">
net.sf.hibernate.transaction.JOTMTransactionManagerLookup
</property>
<property name="jta.UserTransaction">
java:comp/UserTransaction
</property>
好了,现在可以使用网上最常见的代码:
1 javax.transaction.UserTransaction tx =
2 new InitialContext().lookup("java:comp/UserTransaction");
3 tx.begin();
4
5 Session s1 = sf.openSession();
6 ...
7 s1.flush();
8 s1.close();
9
10 ...
11
12 Session s2 = sf.openSession();
13 ...
14 s2.flush();
15 s2.close();
16
17 tx.commit();
得到的utx为null.