用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
qpgong的公告
文章分类
    存档

    原创  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.如果想测试失败的话,大家可以把其中一个数据库中的表删掉。那么第一个数据库中的记录也将插入失败。

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

    发表于 @ 2009年06月19日 11:50:00 | 评论( loading... ) | 编辑| 举报| 收藏

    • 发表评论
    • 评论内容:
    •  
    Copyright © qpgong
    Powered by CSDN Blog