使用tomcat和jotm实现的一个JTA的例子

一、目的:在一个程序中,想达到对oracle数据库与sql server2000数据库的操作通过一个事务来管理,一起提交一起回滚,需要用到JTA。

     参考文档:http://www.blogjava.net/zhanglijun33/archive/2006/09/21/jta.html

二、下面说下我的具体实现:

1、JOTM包:

下载地址:http://jotm.ow2.org/xwiki/bin/view/Main/Download_Releases

我用的是ow2-jotm-dist-2.1.9-bin,由于我使用的是比较新的JOTM版本,所以不需要考虑参考文档中4.1提到的问题。

2、tomcat环境:

(1)版本:5.5.26

(2)commons\lib:把ow2-jotm-dist-2.1.9\lib中的包都放进来。

(3)context.xml:

<Context>

......

<Resource name="jdbc/orcldb"
auth="Container"
type="javax.sql.DataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
driverClassName="oracle.jdbc.driver.OracleDriver"
username="bt_dyw" password="bt_dyw"
url="jdbc:oracle:thin:@localhost:1521:orcl"/>

<Resource name="jdbc/sqldb"
auth="Container"
type="javax.sql.DataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"
username="sa" password="sa"
url="jdbc:microsoft:sqlserver://BJ152:1433;DataBaseName=bt_jszx;SelectMethod=cursor"/>

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

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

......

</Context>

4、web应用中的代码:

index.jsp:

<% @page contentType = " text/html;charset=GB2312 " %>
<% @page import = " java.sql.* " %>
<% @page import = " javax.sql.* " %>
<% @page import = " javax.naming.* " %>
<% @page import = " javax.transaction.UserTransaction " %>
<%
Connection connOracle 
=   null ;
Statement stmtOracle 
=   null ;
ResultSet rsOracle 
=   null ;
Connection connSql 
=   null ;
Statement stmtSql 
=   null ;
ResultSet rsSql 
=   null ;
UserTransaction ut 
=   null ;
try {
    Context initCtx 
=   new  InitialContext();
    Context envCtx 
=  (Context) initCtx.lookup( " java:comp/env " );
    DataSource dsOracle 
=  (DataSource) envCtx.lookup( " jdbc/orcldb " );
    DataSource dsSql 
=  (DataSource) envCtx.lookup( " jdbc/sqldb " );
    ut 
=  (UserTransaction)initCtx.lookup( " java:comp/UserTransaction " );
    connOracle 
=  dsOracle.getConnection();
    connSql 
=  dsSql.getConnection();

    ut.begin();
    System.out.println(
" <<< beginning the transaction >>> " );
    
    stmtOracle 
=  connOracle.createStatement(
    
//  ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE
    );
    rsOracle 
=  stmtOracle.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
    rsOracle.next();
    stmtSql 
=  connSql.createStatement(
    
//  ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE
    );
    rsSql 
=  stmtSql.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
    rsSql.next();
} catch(Exception e) {
    e.printStackTrace();
}
%>
< html >
< body >
Original price Oracle:
<% = rsOracle.getString( " price " ) %>
< br  />Original price Sql:
<% = rsSql.getString( " price " ) %>
< br  />After update Oracle:
<%
PreparedStatement pstmtOracle 
=  connOracle.prepareStatement( " update tm_product set price=? where id=1 " );
pstmtOracle.setInt(
1 , 101 );
pstmtOracle.executeUpdate();
rsOracle 
=  stmtOracle.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
rsOracle.next();
%>
<% = rsOracle.getString( " price " ) %>
< br  />After update Sql:
<%
PreparedStatement pstmtSql 
=  connSql.prepareStatement( " update tm_product set price=? where id=1 " );
pstmtSql.setInt(
1 , 101 );
pstmtSql.executeUpdate();
rsSql 
=  stmtSql.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
rsSql.next();
%>
<% = rsSql.getString( " price " ) %>
<%
System.out.println(
" <<< rolling back the transaction >>> " );
ut.rollback();
// Or  ut.commit();
%>
< br  />After Rollback Oracle:
<%
rsOracle 
=  stmtOracle.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
rsOracle.next();
%>
<% = rsOracle.getString( " price " ) %>
<% connOracle.close(); %>
< br  />After Rollback Sql:
<%
rsSql 
=  stmtSql.executeQuery( " SELECT PRICE FROM TM_PRODUCT WHERE ID=1 " );
rsSql.next();
%>
<% = rsSql.getString( " price " ) %>
<% connSql.close(); %>
</ body >
</ html >

5、测试用数据的准备

oracle中:

create table tm_product(id number(9) primary key,price number(9));

insert into tm_product values(1,1200);

commit;

sql server2000中:

create table tm_product(id numeric(9) primary key,price numeric(9));

insert into tm_product values(1,1500);

6、异常处理

(1)java.lang.ClassCastException: org.objectweb.jotm.Current

我的应用Lib中的jta.jar冲突,去掉后OK

(2)java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Can't start a cloned connection while in manual transaction mode.

参考:http://blog.sina.com.cn/s/blog_4ffb1bf201009ld3.html

7、页面结果展示

Original price Oracle: 1200
Original price Sql: 1500
After update Oracle: 101
After update Sql: 101
After Rollback Oracle: 1200
After Rollback Sql: 1500

 

ps:

ut的timeout设置:

ut.setTransactionTimeout(3600*5);

Spring+iBatis+JOTM实现JTA事务: 如何处理跨库事物:spring + jtom 的jta事务是个很好的选择. 这个源码示例非常不错,包括所有的源码和jar包,下载后eclipse 或 myeclipse 导入就能用。 里面有详细的说明和注释,欢迎下载传播。有问题请在评价中留言,我会及时回复的。 <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/> <!-- JTA事务管理器 --> <bean id="myJtaManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction"> <ref local="jotm"/> </property> </bean> <!-- 数据源A --> <bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> <property name="transactionManager" ref="jotm"/> <property name="driverName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> </bean> </property> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 数据源B --> <bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> <property name="transactionManager" ref="jotm"/> <property name="driverName" value="${jdbc2.driver}"/> <property name="url" value="${jdbc2.url}"/> </bean> </property> <property name="user" value="${jdbc2.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 事务切面配置 --> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* *..servi1ce*..*(..))"/> <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> </aop:config> <!-- 通知配置 --> <tx:advice id="txAdvice" transaction-manager="myJtaManager"> <tx:attributes> <tx:method name="delete*" rollback-for="Exception"/> <tx:method name="save*" rollback-for="Exception"/> <tx:method name="update*" rollback-for="Exception"/> <tx:method name="*" read-only="true" rollback-for="Exception"/> </tx:attributes> </tx:advice ...... ...... ......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值