ow2-jotm-dist + tomcat5.5+ mysql5.5 配置JDBC JTA事务

研究了几天,终于搞出来了tomcat5.5的JTA事务,把我研究历程拿出来分享下...

首先是jotm的介绍,JOTM 是一个基于Java开放源代码的事务处理管理器。它遵循JTA APIs规范与Business Transaction Protocol(BTP)规范以提供了对Web Service的支持。

首先要明白JTA事务他依赖与一定的数据库与应用服务器,比如oracle,mysql等数据库都支持,应用服务器如jboss等,现在如果你不想用应用服务器的话,我们就需要用jotm(java open transaction manager),java 开发的事务管理器。jotm它只是一个事务管理器!仅此而已... 如果大家想在tomcat中配置JTA事务的话,那么JOTM就是你的首选了.....JOTM有好多版本,由于老版本不支持JDK1.5,所以这里抛开了JOTM2.0以前的版本。选择最新版的ow2-jotm-dist, 他可以支持JDK高版本。

下载地址:http://jotm.objectweb.org

步骤如下:

1.下载好jotm后,把jotm解压,jar包放入tomcat中common/lib文件中,记得把数据库的jar也同时放入。

2.在$TOMCAT_HOME/common/classes/下建立carol.properties文件,内容如下

carol.protocols=jrmp
carol.jvm.rmi.local.call=true
carol.start.jndi=false
carol.start.ns=false
carol.jndi.java.naming.factory.url.pkgs=org.apache.naming

3.配置数据源

在你项目的WEBROOT下的META-INF中建立context.xml

配置两个数据源一个事务对象。

4.开启tomcat后,console控制台会输出

09-6-19 10:40:50 (信) Http11BaseProtocol.start : Starting Coyote HTTP/1.1 on http-8088
09-6-19 10:40:50 (信) ChannelSocket.init : JK: ajp13 listening on /0.0.0.0:8099
09-6-19 10:40:50 (信) JkMain.start : Jk running ID=0 time=0/32 config=null
09-6-19 10:40:50 (信) StoreLoader.load : Find registry server-registry.xml at classpath resource
09-6-19 10:40:50 (信) Catalina.start : Server startup in 6235 ms

等信息,证明JOTM配置成功。

5.然后使用上下文InitialContext()获得事务,开启事务-----两个数据源的操作----关闭事务就可以了。下面介绍我的测试例子。

 

例子内容:我把详细文件中的内容拷贝如下,大家可以直接拷出测试。

要求:现在有两个数据库,test,mysql这两个MYSQL5.5的数据库。两个数据库中都有一个customer表,表里面有id 自增长的字段,还有name字段。当用户注册时,同时向这两个数据库中加入数据,如果一方失败,则事务失败。

实现步骤:

我建了一个web project,叫JTA。然后把JOTM包拷入TOMCAT/COMMON/lib下,把carol.properties放入到common/classes下面,内容如上所述。

1.接下来我在项目中META-INF下写了数据源的配置文件context.xml,内容如下:

<Context reloadable="true" >

<Resource name="hibernate/jta1"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="com.mysql.jdbc.Driver"
        username="root" password="123"
        factory="org.objectweb.jotm.datasource.DataSourceFactory"
        url="jdbc:mysql://127.0.0.1:3306/test" />
      
<Resource name="hibernate/jta2"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="com.mysql.jdbc.Driver"
        factory="org.objectweb.jotm.datasource.DataSourceFactory"
        username="root" password="123"
        url="jdbc:mysql://127.0.0.1:3306/mysql" />

    <Resource name="UserTransaction"
            auth="Container"
            type="javax.transaction.UserTransaction" />

    <Transaction factory="org.objectweb.jotm.UserTransactionFactory"
                 jotm.timeout="60" />
              
</Context>

2.写一个实体类Customer

package com.tarena.entity;

import java.io.Serializable;

public class Customer implements Serializable{
private Long id;
private String name;
/**
* @return the id
*/
public Long getId() {
   return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
   this.id = id;
}
/**
* @return the name
*/
public String getName() {
   return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
   this.name = name;
}

}

3.写一个util类,可以通过JNDI名字获得connection对象。

package com.tarena.util;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.*;

public class JDBCUtil {
public static Connection getConnection(String jndi){
   Context ctx;
   Connection con = null;
   try {
    ctx = new InitialContext();
    System.out.println("ctx"+ctx);
    DataSource ds =
             (DataSource)ctx.lookup(jndi);
    con = ds.getConnection();
    System.out.println("con"+con);
   } catch (NamingException e) {
    e.printStackTrace();
   }catch(Exception e){
    e.printStackTrace();
   }
   return con;
}

public static void release(Connection con,Statement sm,ResultSet rs){
    try {
     if(con!=null) con.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
    try {
     if(sm!=null) con.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
    try {
     if(rs!=null) con.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
}
}

 


4.写dao层:一个CustomerDAO接口,一个CustomerDaoImpl实现类。

package com.tarena.dao;

import com.tarena.entity.Customer;

public interface CustomerDao {
public boolean addCustomer(Customer c);
}

package com.tarena.dao;

import java.sql.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import com.tarena.entity.Customer;
import com.tarena.util.JDBCUtil;

public class CustomerDaoImpl implements CustomerDao {
public boolean addCustomer(Customer c) {
   UserTransaction tx = null;
   Connection con = null;
   Connection con1 = null;
   Statement sm = null;
   Statement sm1 = null;
   try {
    Context ctx = new InitialContext();
    System.out.println("ctx"+ctx);//从配置文件中获取事务

    tx =(UserTransaction) ctx.lookup("java:comp/UserTransaction");
            System.out.println("tx"+tx);
    tx.begin();
   
    String sql ="insert into customer(name) values('"+c.getName()+"')";
    //通过工具类,获得jta2数据源的连接
    con = JDBCUtil.getConnection("java:comp/env/hibernate/jta2");
    sm = con.createStatement();
    sm.execute(sql);
    System.out.println("test数据库增加成功");
       //通过工具类,获得jta1数据源的连接
    获得jta2数据源的连接con1 = JDBCUtil.getConnection("java:comp/env/hibernate/jta1");
    sm1 = con1.createStatement();
    sm1.execute(sql);
    System.out.println("mysql数据库增加成功");
   
    tx.commit();
   
    return true;
   
   }catch (Exception e) {
    e.printStackTrace();
    try {
     tx.rollback();
    } catch (IllegalStateException e1) {
     e1.printStackTrace();
    } catch (SecurityException e1) {
     e1.printStackTrace();
    } catch (SystemException e1) {
     e1.printStackTrace();
    }
    e.printStackTrace();
    return false;
   }finally{
    JDBCUtil.release(con, sm, null);
    JDBCUtil.release(con1, sm1, null);
   }
}
}

5.然后在写了一个servlet,servlet doPost()方法中如下所写:

package com.tarena.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.tarena.dao.*;
import com.tarena.entity.*;

public class CustomerServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
private CustomerDao cd = new CustomerDaoImpl();

public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   System.out.println("进来了servlet");
   String name = request.getParameter("name");
   System.out.println("name"+name);

   Customer c = new Customer();
   c.setName(name);
  
   boolean b = cd.addCustomer(c);
  
   System.out.println(b?"增加成功":"增加失败");
  
}
}

6.在web.xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>
<servlet-name>registerServlet</servlet-name>
<servlet-class>com.tarena.servlet.CustomerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>registerServlet</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>


<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

7.写一个register.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>register.html</title>
</head>

<body>
<center>
    <form action="register" method="post">
    name:<input type="text" name="name"><br>
   <input type="submit" value="submit">   
    </form>
    </center>
</body>
</html>

8,接下来开启服务器。

地址栏输入http://localhost:8080/JTA/register.html

然后执行就可以。

9.如果想测试失败的话,大家可以把其中一个数据库中的表删掉。那么第一个数据库中的记录也将插入失败。

 

好了,如果有没有测试成功的,可以联系我...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值