首页 技术 正文
技术 2022年11月23日
0 收藏 573 点赞 3,216 浏览 4189 个字

这个是昨天上班的时候,写一个后台程序的调试程序时碰到的问题,和项目经理纠结了一天,最后搞定了。于是今天上班正好闲着,花了几乎一天的时间去网上找各种相关的资料。目前了解的内容如此:

根据使用的weblogic数据库驱动不同,可能会有两种报错:

①     Cannot call commit/rollback when using distributed transactions.

②     Cannot call Connection.commit/rollback in distributed transaction.

在JavaRanch上找到一个贴子,对解决问题非常有帮助:
http://www.coderanch.com/t/316208/EJB-JEE/java/Distributed-transaction-connnection-commit

其中的两个回复:
(1)这可能是因为你使用的数据库驱动启用了分布式事务(XA)。
检查一下weblogic控制台中的数据库驱动,你可能需要改一下,让它指向一个不用XA驱动的连接池。

(2)有两种方法可以实现事务:用JDBC,或者用JTA/JTS。第二种方法可以从ejb context中获取UserTransaction来实现:

UserTransaction ut = context.getUserTransaction();
ut.begin();
//do business logic
ut.commit();

  

两种模式之间有一个巨大的不同之处——只有第二种支持全局事务。
一些容器可能为了支持全局事务,会有一些特殊的数据库设定(比如容器将一直创建一个TX数据库(支持JTA的数据库),尽管基础连接池用的却是一个非XA的JDBC驱动)。可能因为如此,一使用JDBC事务就会出现这样的失败。

■总结:根据(1),最初设定数据库时的驱动选的不对。我选的是oracle.jdbc.xa.client.OracleXADataSource,这个支持分布式事务,必须要用UserTransaction接口对应的方法才能实现事务的提交和回滚操作,所以应该换用非XA的oracle.jdbc.OracleDriver驱动才对。但是仅仅这样,仍然还是会报错,只不过报错内容从①变成②。于是回复(2)解释了原因,虽然oracle.jdbc.OracleDriver并不是XA驱动,但是它为了支持全局事务,做了特殊的设定,容器在一直创建支持JTA的TX数据库,于是报了错。所以还应该在trasaction选项中把“支持全局事务”这一项的勾给去掉。这样就解决了。

按照以上的做法,就能解决问题了。如果身为开发者,还坚持要继续使用分布式事务的话,那就不要用JDBC的提交、回滚方法,而是要用JTA——实现一个UserTransaction的接口,然后用它的方法吧。

因为对于J2EE,本人还是newbie,好多东西都不知道,于是走了不少弯路。即便是把一切解决了,还是有诸多疑问。尤其是回复中的那些花样繁多的名词……于是又继续研究了一下,发现很是坑爹。

以下是查看的相关资料:

(a)http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html

两种事务的基本概念——全局事务、本地事务:

全局事务:资源管理器管理和协调的事务,可以跨越多个数据库和进程。资源管理器一般使用XA二阶段提交协议与“企业信息系统”(EIS) 或数据库进行交互。

本地事务:在单个 EIS 或数据库的本地并且限制在单个进程内的事务。本地事务不涉及多个数据来源。

本地和全局事务都使用 javax.transaction.UserTransaction 接口划分界限,客户端必须使用此接口。本地事务不使用事务管理器,因而处理速度更快。

起初,所有事务都是本地的。如果非 XA 数据源连接是事务范围中登记的第一个资源连接,当“另一个”XA 数据源连接加入此连接时,该非 XA 数据源连接就成为全局事务。如果另一个非 XA 数据源连接试图加入,就会产生异常。

J2EE开发者有两个事务管理的选择: 全局 或 本地 事务。全局事务由应用服务器管理,使用JTA。局部事务是和资源相关的,比如一个和JDBC连接关联的事务。这个选择有深刻的含义。例如,全局事务可以用于多个事务性的资源(典型例子是关系数据库和消息队列)。使用局部事务,应用服务器不需要参与事务管理,并且不能帮助确保跨越多个资源(需要指出的是多数应用使用单一事务性的资源)的事务的正确性。

全局事务.  全局事务有一个重大的缺陷,代码需要使用JTA:一个笨重的API(部分是因为它的异常模型)。此外,JTA的UserTransaction通常需要从JNDI获得,这意味着我们为了JTA,需要 同时 使用JNDI 和 JTA。显然全部使用全局事务限制了应用代码的重用性,因为JTA通常只在应用服务器的环境中才能使用。 以前,使用全局事务的首选方式是通过EJB的 CMT(容器管理事务):CMT是 声明式事务管理 的一种形式(区别于 编程式事务管理)。EJB的CMT不需要任何和事务相关的JNDI查找,虽然使用EJB本身肯定需要使用JNDI。它消除了大多数(不是全部)硬编码的方式去控制事务。重大的缺陷是CMT绑定在JTA和应用服务器环境上,并且只有我们选择使用EJB实现业务逻辑,或者至少处于一个事务化EJB的外观(Facade)后才能使用它。EJB有如此多的诟病,尤其是存在其它声明式事务管理时,EJB不是一个吸引人的建议。

本地事务. 本地事务容易使用,但也有明显的缺点:它们不能用于多个事务性资源。例如,使用JDBC连接事务管理的代码不能用于全局的JTA事务中。另一个缺点是局部事务趋向于入侵式的编程模型。

(b)XA连接区别于非XA连接。

XA连接区别于非XA连接。要记住的是XA连接是一个JTA事务中的参与者。这就意味着XA连接不支持JDBC的自动提交特性。也就是说应用程序不必在XA连接上调用java.sql.Connection.commit()或java.sql.Connection.rollback()。 相反,应用程序应该使用UserTransaction.begin()、UserTransaction.commit()和UserTransaction.rollback()。

(c)http://hi.baidu.com/logson/blog/item/d32db308e750258ad0581b69.html

从程序角度考虑,事务可以分为两大类:一种是本地事务,一种是全局事务(也叫分布式事务)。

本地事务:是针对某个独立的事务资源(如JDBC)操作的事务。

全局事务:是协同或横跨多个资源(如JDBC连接、数据库等)操作的事务(上下文),多个资源协作是由事务管理器来完成的

JDBC与JTA:

JDBC是Java database connectivity 的缩写,意思是Java数据库连接。一般本地事务是与一个数据库连接相关的,因此Java中常称本地事务为JDBC事务。JDBC本身提供了简单的本地事务控制,可以满足针对一个JDBC连接事务的需求。

JTA是Java Transaction API的缩写,意思是Java事务API,这是一种组复杂事务控制接口,这组接口作为J2EE规范暴露给容器开发商,一般都由J2EE容器来实现。Spring很牛,也实现了这组API,使得任何应用使用JTA事务变得更容易。

(d)http://hi.baidu.com/eredlab/blog/item/d78c2538e45894e6b311c764.html

全局事务亦即常说的分布式事务:

全局事务需要应用服务器的支持,使用JTA。全局事务可以用于多个事务性的资源。(典型的为跨越多个数据库或者消息队列)。

本地事务:

应用服务器不需要参与事务管理。只针对单一事务资源。不能跨越多个事务资源。

XA:

XA是指X/Open组织在分布式规范中定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商提供。

(e)connect.commit和UserTransaction.commit的区别:
http://www.coderanch.com/t/307456/JDBC/java/Difference-between-connection-commit-usertransaction
前者由数据库执行,后者由用户执行。
他们是不同的东西。想象一下,一个事务中包含了好几个数据库连接。提交用户的事务将会把这些都给一同commit上去。但是提交其中一个连接时却只commit一个。

■ 结论:全局事务常被称为分布式事务,而常说的JDBC事务即是本地事务。XA是组织在分布式中的接口规范,所以带XA字样的数据库驱动一般启用的都是分布式事务。而JTA是JAVA事务API的缩写(顺带一提,JTS是JAVA事务服务的缩写),一般说的JTA事务也是指分布式事务。所以前边说的看起来好像是有好几种事务似的,但是其实他们都是一回事,归结起来就只有两种而已,一种是分布式的,一种是非分布式的,发生的错误归结起来就是一句话:别在任何支持分布式事务的东西里用非分布式的commit和rollback方法,不好用……完毕。真是各种坑爹,一物多名真是初学者杀手啊。

现在再回顾一下之前的回复(2)中说的内容。分布式事务必须通过JTS来获取UserTransaction的接口才能得以实现。所以之前在分布式中调用JDBC事务的方法,才会出现异常。而后来换的那个虽然不是XA的驱动,但是他为了支持全局事务(就是分布式事务),一直在创建一个支持JTA的TX数据库,所以还是报了错。想正常地使用JDBC事务,必须保证用的不是XA驱动,同时全局事务支持必须关掉,二者缺一不可,和分布式一点儿边也不能沾。

详细的,这还有一篇文章介绍这方面的基础知识的:
http://www.ibm.com/developerworks/cn/java/j-dao/

http://www.programgo.com/article/81382059720/

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,992
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,506
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,349
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,134
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,767
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,844