`

JOTM 分布式事务初探(JNDI,Tomcat 7 JDBC Pool连接池)

阅读更多

JOTM 分布式事务初探(JNDI,Tomcat 7 JDBC Pool连接池)

 

Tomcat 7 带了一个新的连接池 tomcat(The Tomcat JDBC Connection Pool)

网上有人测试,据说性能超过常用连接池(c3p0等).

链接:http://www.open-open.com/lib/view/open1329182303124.html

并且这个连接池提供的连接不是普通的Connection,而是pooledConnection,

而且支持提供XADataSource(org.apache.tomcat.jdbc.pool.XADataSource).

 

The Tomcat JDBC Connection Pool可独立使用,

需要Tomat7版本下lib包中的tomcat-jdbc.jar和bin中的tomcat-juli.jar

 

可以用来做JOTM的分布式事务的数据源.

 

实际使用tomcat版本 是5.5.25

 

JOTM版本 2.1.9 http://jotm.ow2.org/xwiki/bin/view/Main/Download_Releases

 

1. 新建一个Java web工程

 

   将JOTM的lib包下的所有jar包(包括一个空的ext文件夹)拷贝到web-inf的lib下

   

   将Tomcat版本中的tomcat-jdbc.jar和tomcat-juli.jar拷贝到

   tomcat5.5.25的common\lib下,并引入到工程中来.

   

   将 mysql和oracle的jdbc驱动拷贝到web-inf的lib下

   (classes12.jar--oracle驱动,mysql-connector-java-5.1.24-bin.jar--mysql驱动)

   

   需要将web-inf的lib下所有jar包拷贝到tomcat5.5.25的common\lib下,部署的时候,注意将

   webapps\工程\web-inf的lib下的jar全部删除,使用tomcat5.5.25的common\lib下的jar包

 

2. 分别在mysql和oracle中创建测试数据库和测试用户

 

   2.1 mysql数据库(mysql 版本mysql  Ver 14.14 Distrib 5.5.11, for Win32 (x86))

   下面的语句执行前,可能需要使用root用户登陆

   

GRANT ALL PRIVILEGES ON *.* TO mojo@localhost IDENTIFIED BY 'jojo' WITH GRANT OPTION; -- 创建用户,并授权
   create database javatest;
   use javatest;
   create table testdata (id int not null auto_increment primary key,foo int) engine = innodb;
   create unique index index_idfoo on testdata(id,foo); --创建唯一索引

 

   

   2.2 oracle数据

   

   

create user mojo identified by jojo;
   grant dba to mojo;--授予DBA权限  
   connect mojo/jojo@serviceid; -- 使用刚刚创建的用户登陆 serviceid 需要修改成实际的
   create table testdata (id number(10),foo number(10)); --创建一个表
   create unique index index_idfoo on testdata(id,foo);
   commit;

 

   

3. 配置carol.properties,放置到src目录下面

 

    # # JNDI (Protocol Invocation)

    carol.protocols=jrmp

    

    # Local RMI Invocation

    carol.jvm.rmi.local.call=true

    

    # do not use CAROL JNDI wrapper

    carol.start.jndi=false

    

    # do not start a name server

    carol.start.ns=false

    

    # Naming Factory

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

   

4. 配置tomcat/conf/context.xml

 

  

<?xml version="1.0" encoding="UTF-8"?>
  <Context>
      <Resource name="jdbc/mysqlDB"
            auth="Container"
            type="javax.sql.DataSource"
            factory="org.objectweb.jotm.datasource.DataSourceFactory"
            testWhileIdle="true"
            testOnBorrow="true"
            testOnReturn="false"
            validationQuery="SELECT 1"
            validationInterval="30000"
            timeBetweenEvictionRunsMillis="30000"
            maxActive="100"
            minIdle="10"
            maxWait="10000"
            initialSize="10"
            removeAbandonedTimeout="60"
            removeAbandoned="true"
            logAbandoned="true"
            minEvictableIdleTimeMillis="30000"
            jmxEnabled="true"
            jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
              org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
            username="mojo"
            password="jojo"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://127.0.0.1:3306/javatest"/>
            
      <Resource name="jdbc/oracleDB"
            auth="Container"
            type="javax.sql.DataSource"
            factory="org.objectweb.jotm.datasource.DataSourceFactory"
            testWhileIdle="true"
            testOnBorrow="true"
            testOnReturn="false"
            validationQuery="SELECT 1"
            validationInterval="30000"
            timeBetweenEvictionRunsMillis="30000"
            maxActive="100"
            minIdle="10"
            maxWait="10000"
            initialSize="10"
            removeAbandonedTimeout="60"
            removeAbandoned="true"
            logAbandoned="true"
            minEvictableIdleTimeMillis="30000"
            jmxEnabled="true"
            jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
              org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
            username="mojo"
            password="jojo"
            driverClassName="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@10.47.170.175:1521:zxin"/>
            
      <!-- Resource configuration for UserTransaction
             use JOTM
      -->
      <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
         
  
      <WatchedResource>WEB-INF/web.xml</WatchedResource>
  	
      <!-- Uncomment this to disable session persistence across Tomcat restarts -->
      <!--
      <Manager pathname="" />
      -->
  
  </Context>

 上面配置文件中 factory="org.objectweb.jotm.datasource.DataSourceFactory"

 表示使用的是JOMT自己的连接池.

 而配置成 factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"

 表示使用 Tomcat 7 JDBC 连接池

 

注意上面配置数据库连接时,

type="javax.sql.DataSource"

factory="org.objectweb.jotm.datasource.DataSourceFactory"

两个属性,type总是DataSource,尽管JOTM要求提供XADataSource,

主要是factory="org.objectweb.jotm.datasource.DataSourceFactory"这个可以根据需要

选择提供普通的DataSource或者XADataSource.

这样,假如之前有相关的配置,则修改为支持JOTM分布式事务时,貌似只要修改这个

factory配置即可.

 

<Transaction>是Tomcat 5中的新标记,对于不支持此标记的老版本,

需要使用以下语句代替事务资源的声明:

 

<!-- Resource configuration for UserTransaction
use JOTM
-->
<Resource name="UserTransaction" auth="Container"
type="javax.transaction.UserTransaction"
factory = "org.objectweb.jotm.UserTransactionFactory"
jotm.timeout = "60"/>

 

需要注意的是,使用<Resource>节点声明的资源默认上下文前缀是"java:comp/env",

而使用< Transaction>节点时则是"java:comp"。因此,当使用4.2的方式声明用户事务时,

相应的JNDI查找代码也应该改为 

UserTransaction ut = (UserTransaction)initCtx.lookup("java:comp/env/UserTransaction");

上面的配置还配置了一个 UserTransaction.

 

5. 在Java类中获取上面配置的资源

 

   

Context ctx = new InitialContext();

   // JDBC stuff
   DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mysqlDB"); //mysql数据源
      
   DataSource dsOra = (DataSource) ctx.lookup("java:comp/env/jdbc/oracleDB");//oarcle数据源
      
   UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction"); //用户事务(分布式)

 

   

6. 测试分布式事务.

 

   上面在mysql和oracle中分别创建了一个表,并且表里面数据不能重复.

   

   初始化时在mysql中插入一条语句:

   insert into testdata(id,foo) values(1,1);

   

   然后在程序中处理:

   (1) 启动用户事务

   (2) 在oracle中插入语句insert into testdata(id,foo) values(1,1); --oracle是首次插入这个语句

   (3) 在mysql中重复插入数据

   (4) 如果一切正常提交事务,否则回滚事务

   

   分析: 假如不使用分布式事务,则oracle插入数据成功,mysql插入数据失败(重复插入).

   但是现在使用分布式事务,回滚时,导致oracle中的数据也回滚.

   所以上面4个步骤执行完毕后,oracle中仍然没有数据.

   

   测试代码:

   

package foo;

import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;

public class DBTest
{

  int foo = -1;

  // value stored in DB

  public void init(String completion)
  {
    UserTransaction ut = null;
    try
    {
      Context ctx = new InitialContext();

      // mysql数据源
      DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mysqlDB");
      //oracle数据源
      DataSource dsOra = (DataSource) ctx.lookup("java:comp/env/jdbc/oracleDB");
      //用户事务(分布式)
      ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
      
      
      java.sql.Connection conn = ds.getConnection();
      java.sql.Connection connOra = dsOra.getConnection();
      
      System.out.println("<<< beginning the transaction >>>");
      ut.begin();
      
      //oracle中插入数据
      Statement stmtOra =connOra.createStatement();
      stmtOra.execute("insert into testdata(id,foo) values(1,1)");

      // mysql中插入数据(之前表里面已经有一样的数据,导致下面的插入数据失败)
      Statement stmt = conn.createStatement();
      stmt.execute("insert into testdata(id,foo) values(1,1)");
      //mysql 中插入失败导致整个事务回滚,oracle也回滚了,导致oracle中仍然没有数据.
      

      System.out.println("<<< committing the transaction >>>");
      ut.commit();

      stmt.close();
      stmtOra.close();

      conn.close();
      connOra.close();
      
      System.out.println("<<< done >>>");
    }
    catch (Exception e)
    {
      try
      {
        System.out.println("<<< rollbacking the transaction >>>");
        ut.rollback();
      }
      catch (Exception es)
      {
        System.out.println("rollbacking error >> ");
        es.printStackTrace();
      }
      
      System.out.println("DBTest >> ");
      e.printStackTrace();
    }
  }

  public String getFoo()
  {
    return "" + foo;
  }
}

 

   

参考 :http://static.raibledesigns.com/downloads/howto-tomcat-jotm.html

 

http://static.raibledesigns.com/downloads/howto-tomcat-jotm.html

 

http://www.blogjava.net/nokiaguy/archive/2008/05/08/199150.html

   

   

   附件为工程文件,需要重新命名

   TestJomt001.7z 重命名 TestJomt.7z .001

   TestJomt002.7z 重命名 TestJomt.7z .002

    

 

 

 

 

分享到:
评论

相关推荐

    Spring+JOTM 分布式事务管理

    Spring框架作为一个广泛使用的Java应用程序开发框架,提供了多种支持事务管理的解决方案,其中包括集成JOTM(Java Open Transaction Manager)来处理分布式事务。本文将深入探讨Spring与JOTM结合使用的知识点,帮助...

    spring JTA集成JOTM或Atomikos配置分布式事务(Tomcat应用服务器)

    本文将深入探讨如何在Tomcat应用服务器上集成JTA,并使用JOTM(Java Open Transaction Manager)或Atomikos作为事务管理器来实现分布式事务。 首先,我们需要理解JTA的核心概念。JTA是Java EE平台的一部分,提供了...

    jta分布式事务完成例子,测试通过

    例子虽小,可覆盖面广,设计spring载入.properties文件,spring配置jta和jotm分布式事务,设置数据源连接池,注解事务驱动。功能是在mysql上建立了两个数据库分别为dbone和dbtwo,在dbone里有表tb1,表中只有一个字段...

    使用JOTM实现分布式事务管理(多数据源)

    JOTM是Java世界里一个开源的事务管理器,遵循JTA(Java Transaction API)规范,提供了分布式事务处理的能力。在多数据源环境中,JOTM可以帮助我们处理复杂的事务边界,保证在不同的数据库或服务之间的一致性,即使...

    spring + JTA + JOTM实现分布式事务

    本教程将深入探讨如何使用Spring框架、Java Transaction API (JTA) 和 Java Open Transaction Manager (JOTM) 来实现这样的分布式事务管理。 首先,我们来了解一下JTA。JTA是Java平台的标准事务API,它允许应用程序...

    spring+jotm+ibatis+mysql实现JTA分布式事务

    本项目“spring+jotm+ibatis+mysql实现JTA分布式事务”旨在利用这些技术来确保在分布式环境中的数据一致性。下面将详细介绍这个项目所涉及的知识点。 首先,Spring框架是Java开发中最常用的应用框架之一,它提供了...

    spring+jotm 多数据源事务管理(三)JNDI+Tomcat

    ### Spring + JOTM 多数据源事务管理详解(三):JNDI + Tomcat 在本篇文章中,我们将深入探讨如何利用Spring框架结合JOTM(Java Open Transaction Manager)来实现多数据源下的分布式事务管理。我们将通过具体实例...

    Spring分布式事务实现

    总结来说,Spring分布式事务实现主要依赖于Spring框架的事务管理能力、JOTM作为JTA实现的事务管理器,以及相关的JDBC驱动来连接数据库。通过声明式事务管理,开发者可以在不深入事务管理细节的情况下,编写出可靠的...

    开源分布式事务管理Jtom

    【标题】"开源分布式事务管理Jtom"是一个关键的话题,主要关注的是在Java环境中如何高效地管理和协调跨多个数据源的事务。Jtom,全称为Java Open Transaction Manager,是实现这一目标的重要工具。它是一个完全遵循...

    Tomcat中使用JOTM2.14

    例如,你可能需要指定JOTM应该使用哪种事务日志实现,以及如何连接到不同的资源管理器。正确配置这些参数对于优化性能和确保事务处理的可靠性至关重要。 再者,`context.xml`文件在Tomcat中是每个Web应用程序的上...

    Spring+Jotm+Hibernate+Oracle+Junit 实现JTA分布式事务要求Demo工程

    2.Spring+Jotm整合实现JTA分布式事务,应用场景如转账等,同一事务内完成db1用户加100元、db2用户减100元。 3.Spring+Junit4单元测试,优点:不会破坏数据库现场,等等。 (特别注意:Spring3.0里不在提供对jotm的...

    分布式事务的介绍

    而在Tomcat等轻量级服务器中,则需要借助外部框架如Jotm、Atomikos来实现分布式事务。 **特点**: - 实现相对简单,适用于单体应用中跨库操作的需求。 - 对性能影响较大,不适合高并发场景。 #### 四、本地消息表...

    20170830-分布式事务解决方案1

    JOTM(Java Open Transaction Manager)和Atomikos是两个实现JTA的开源事务管理器,它们提供了在互联网分布式环境下的事务管理解决方案。 总的来说,分布式事务是确保大规模分布式系统数据一致性的关键技术。从2PC...

    jotm 的 jar

    XAPool 是一个高效的连接池实现,通常用于JDBC连接管理。在JOTM中,XAPool jar 文件(xapool.jar)的作用是提供连接池服务,允许JOTM更有效地管理和复用数据库连接,减少创建和销毁连接的开销,提高系统性能和资源...

    JOTM简单测试DEMO(不含jar包)

    本DEMO主要展示了如何在Spring框架中结合JOTM来处理分布式事务,特别是涉及多个数据源的情况。 首先,我们需要理解JOTM的基本概念。JOTM作为一个事务协调者,负责管理跨多个资源的事务,确保它们要么全部成功,要么...

Global site tag (gtag.js) - Google Analytics