JTA事务和JDBC事务

2024-06-07 06:08
文章标签 jdbc 事务 jta

本文主要是介绍JTA事务和JDBC事务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一般情况下,J2EE应用服务器支持JDBC事务、JTA事务、容器管理事务。这里讨论JTA和JDBC事务的区别。这2个是常用的DAO模式事务界定方式。 
JDBC 事务 
JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 
★ 在jdbc中,事务操作缺省是自动提交。也就是说,一条对数据库的更新表达式代表一项事务操作,操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回滚。 

★ 在jdbc中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;此时就可以在异常捕获时调用rollback()进行回滚。这样做可以保持多次更新操作后,相关数据的一致性,示例如下: 

try {conn = DriverManager.getConnection    ("jdbc:oracle:thin:@host:1521:SID","username","userpwd";conn.setAutoCommit(false);//禁止自动提交,设置回滚点stmt = conn.createStatement();stmt.executeUpdate(“alter table …”); //数据库更新操作1stmt.executeUpdate(“insert into table …”); //数据库更新操作2conn.commit(); //事务提交}catch(Exception ex) {    ex.printStackTrace();try {conn.rollback(); //操作不成功则回滚}catch(Exception e) {e.printStackTrace();}}

JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。 

JTA事务 

JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。 
要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。例如:
 utx.begin(); 

 // ...DataSource ds = obtainXADataSource();Connection conn = ds.getConnection();pstmt = conn.prepareStatement("UPDATE MOVIES ...");pstmt.setString(1, "Spinal Tap");pstmt.executeUpdate();// ...utx.commit();

让我们来关注下面的话: 
“用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。” 
要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。 
XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。 
     Note: 


Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持分布事务。 
My SQL 连本地都支持不好,更别说分布事务了。 
JTA方式的实现过程: 
   用XADataSource产生的XAConnection它扩展了一个getXAResource()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了,别的都是黑箱操作。 
在使用JTA之前,你必须首先实现一个Xid类用来标识事务(在普通情况下这将由事务管理程序来处理)。Xid包含三个元素:formatID、gtrid(全局事务标识符)和bqual(分支修饰词标识符)。 
下面的例子说明Xid的实现:
 

import javax.transaction.xa.*; 
public class MyXid implements Xid 
{ protected int formatId; protected byte gtrid[]; protected byte bqual[]; public MyXid() { } public MyXid(int formatId, byte gtrid[], byte bqual[]) { this.formatId = formatId; this.gtrid = gtrid; this.bqual = bqual; } public int getFormatId() { return formatId; } public byte[] getBranchQualifier() { return bqual; } public byte[] getGlobalTransactionId() { return gtrid; } }

其次,你需要创建一个你要使用的数据库的数据源:

public DataSource getDataSource() throws SQLException { SQLServerDataSource xaDS = new com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource(); xaDS.setDataSourceName("SQLServer"); xaDS.setServerName("server"); xaDS.setPortNumber(1433); xaDS.setSelectMethod("cursor"); return xaDS; 
} 


例1?这个例子是用“两步提交协议”来提交一个事务分支:  

XADataSource xaDS; 
XAConnection xaCon; 
XAResource xaRes; 
Xid xid; 
Connection con; 
Statement stmt; 
int ret; 
xaDS = getDataSource(); 
xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password"); 
xaRes = xaCon.getXAResource(); 
con = xaCon.getConnection(); 
stmt = con.createStatement(); 
xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02}); 
try { xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("insert into test_table values (100)"); xaRes.end(xid, XAResource.TMSUCCESS); ret = xaRes.prepare(xid); if (ret == XAResource.XA_OK) { xaRes.commit(xid, false); } 
} 
catch (XAException e) { e.printStackTrace(); 
} 
finally { stmt.close(); con.close(); xaCon.close(); 
}

当然,实际过程中,我们不需要写这些代码,这些代码是JTA最终的实现代码。 
关于“两步提交协议”,可以参看下面的文章:
 

http://www.jspcn.net/htmlnews/11049371131251752.html 



选择最好的方式 
用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下: 

事务界定代码嵌入在 DAO 类中。 
DAO 类使用 JDBC API 进行事务界定。 
调用者不能界定事务。 
事务范围局限于单个 JDBC 连接。 
JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库,那么下列实现策略也许更合适: 

事务用 JTA 界定。 
事务界定代码从 DAO 中分离出来。 
调用者负责界定事务。 
DAO 加入一个全局事务。 
JDBC 方式由于其简单性而具有吸引力,JTA方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。 


XADataSource例子:
 

<?xml version="1.0" encoding="UTF-8"?><!-- ===================================================================== -->
<!--    -->
<!--  JBoss Server Configuration    -->
<!-- Thanks to Horia Muntean <horia@bvb.ro>   -->
<!-- ===================================================================== --><!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ --><datasources><!--XADatasource for DB2 V8.1 (app driver)copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib--><xa-datasource><jndi-name>DB2XADS</jndi-name><xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class><xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property><xa-datasource-property name="User">your_user</xa-datasource-property><xa-datasource-property name="Password">your_password</xa-datasource-property></xa-datasource>
</datasources>


转载自:http://walsh.iteye.com/blog/258002



这篇关于JTA事务和JDBC事务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1038360

相关文章

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

SpringBoot嵌套事务详解及失效解决方案

《SpringBoot嵌套事务详解及失效解决方案》在复杂的业务场景中,嵌套事务可以帮助我们更加精细地控制数据的一致性,然而,在SpringBoot中,如果嵌套事务的配置不当,可能会导致事务不生效的问题... 目录什么是嵌套事务?嵌套事务失效的原因核心问题:嵌套事务的解决方案方案一:将嵌套事务方法提取到独立类

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

Hibernate框架中,使用JDBC语法

/*** 调用存储过程* * @param PRONAME* @return*/public CallableStatement citePro(final String PRONAME){Session session = getCurrentSession();CallableStatement pro = session.doReturningWork(new ReturningWork<C

spring事务属性的xml格式配置

实际是使用代理做的事务优化 <!--配置事务的属性--><tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--匹配所有以add开头的方法--><tx:method name="add*" propagation="REQUIRED" /> <tx:metho

Spring Cloud整合Seata实现分布式事务

文章目录 1.Seata1.1 官网1.2 下载1.3 通过安装包运行seata1.3.1 解压seata-server-1.3.0.zip1.3.2 修改 conf/file.conf 配置文件1.3.3 修改conf/registry.conf配置文件1.3.4 添加seata配置信息到nacos1.3.5 配置seata服务端数据库表结构1.3.6 启动seata 2.Spring

jdbc连接数据库使用sid和service_name的区别 ?

问题描述: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor The Connection descriptor used by the client was: 10.12.162.84:1521:xxxx  oracle数据的tnsnames.ora中配置的是:SERVICE

Java项目中,配置打印 JDBC 日志的几种方法

在 IDEA 项目中,如果你想打印 JDBC 日志,可以通过配置日志框架(如 Logback 或 Log4j)来实现。Spring Boot 使用的默认日志框架是 Logback,你可以通过在 application.yml 文件中配置日志级别来打印 JDBC 日志。 方法 1: 使用 application.yml 配置 JDBC 日志 logging:level:# 显示 SQL 语句co