Tomcat6集成JOTM实现JTA事务管理

来源:互联网 发布:知乎离线 编辑:程序博客网 时间:2024/06/11 00:31

JTA(Java Transaction API )java事务API,主要实现分布式事务管理,跟JDBC主要区别在于JTA可以跨连接,而JDBC事务需要依赖于连接的生命周期

Tomcat是servlet容器,并不支持JTA,需要集成JOTM实现分布式事务管理。

JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现,它本身也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分,为其提供JTA支持和分布式事务管理。JOTM同样可以为Tomcat提供JTA支持,以下将对相关的配置进行简单说明

 

测试环境:

apache-tomcat-6.0.35

ow2-jotm-dist-2.2.1

SQL Server 2005

 

1添加JOTM JAR文件

将jotm解压后lib文件夹里面的所有jar拷贝到%TOMCAT%/lib目录里面,

还需要把数据库驱动拷贝到%TOMCAT%/lib目录里面(我的数据库驱动是sqljdbc.jar)

 

2配置JOTM

新建carol.properties文件,放在%TOMCAT_HOME%/lib目录下,内容如下:

 # JNDI调用协议
carol.protocols=jrmp

#本地RMI调用
carol.jvm.rmi.local.call=falsecarol.start.jndi=false

#不使用CAROL的JNDI封装器

carol.start.jndi=false

#不启用命名服务器

carol.start.ns=false

#命名工厂类

carol.jndi.java.nameing.factory.url.pkgs=org.apache.nameing

 

3配置TOMCAT

在%TOMCAT_HOME%/conf/context.xml添加如下内容:

<Resource name="jdbc/afunms"
        auth="Container"
        type="javax.sql.DataSource"
        factory="org.objectweb.jotm.datasource.DataSourceFactory"
        driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        username="username"
     password="password"        
     url="jdbc:sqlserver://localhost:1433;databaseName=hibernate" />
  <Resource name="UserTransaction"
            auth="Container"
            type="javax.transaction.UserTransaction" />
  <Transaction factory="org.objectweb.jotm.UserTransactionFactory"
               jotm.timeout="60" />

 

4测试:

UserTransaction trans = null;
  Connection con = null;
  Statement sta = null;
  ResultSet res = null;

  Context initCtx;
  Context envCtx;
  DataSource ds;
  try {
   initCtx = new InitialContext();
   envCtx = (Context) initCtx.lookup("java:comp/env");
   ds = (DataSource) envCtx.lookup("jdbc/afunms");
   trans = (UserTransaction) initCtx
     .lookup("java:comp/UserTransaction");
   con = ds.getConnection();
  } catch (Exception e) {
   e.printStackTrace();
  }

  try {
   trans.begin();
   System.out.println("<<< beginning the transaction >>>");
  } catch (NotSupportedException e) {
   e.printStackTrace();
  } catch (SystemException e) {
   e.printStackTrace();
  }

  try {
   System.out.println("access1");
   String sql = null;
   sta = con.createStatement();
   sql = "SELECT * FROM tb_user WHERE ID= 1";
   res = sta.executeQuery(sql);
   System.out.println("2");
   while (res.next()) {
    System.out.println("ID=" + res.getInt(1));
    System.out.println("name=" + res.getString(2));
    System.out.println("password=" + res.getString(3));
    System.out.println("age=" + res.getInt(4));
    System.out.println("sex=" + res.getString(5));
   }
   System.out.println("--------------------------");
   sql = "UPDATE tb_user SET username ='zhang' WHERE ID= 1";
   sta.executeUpdate(sql);

   sql = "SELECT * FROM tb_user WHERE ID= 1";
   res = sta.executeQuery(sql);
   while (res.next()) {
    System.out.println("ID=" + res.getInt(1));
    System.out.println("name=" + res.getString(2));
    System.out.println("password=" + res.getString(3));
    System.out.println("age=" + res.getInt(4));
    System.out.println("sex=" + res.getString(5));
   }
  } catch (Exception e) {
   e.printStackTrace();
  }

  try {
   System.out.println("access2");
   trans.commit();
  } catch (Exception e) {
   System.out.println("提交事务异常");
   e.printStackTrace();
  }
  
  try {
   if (res != null)
    res.close();
   if (sta != null)
    sta.close();
   if (con != null)
    con.close();
  } catch (Exception ex) {
   ex.printStackTrace();
  }

 

以上代码放在一个servlet的dopost或者doget方法中测试

 

总结:1对于集成hibernate进行JTA事务管理时,应该把hibernate里面的jta.jar和login.jar包删除掉,因为jotm中存在于jta类似的包,会发生冲突

           2在hibernate使用JTA的时候,在提交事务之前session应该session.flush();不然会出现事务不提交的情况

           3在配置JOTM的时候carol.jvm.rmi.local.call 必需设置成false,否则在运行时会报如下错误:
              java.lang.NoSuchMethodError: sun.rmi.transport.ObjectTable.getStub(Ljava/rmi/Remote;)