JTA

http://aixiangct.blog.163.com/blog/static/9152246120113251636706/


Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。    

   事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。
       这样可以防止出现脏数据,防止数据库数据出现问题。开发中为了避免这种情况一般都会进行事务管理。

JDBC中是通过Connection对象进行事务管理的
Hibernate中是通过Transaction进行事务管理,处理方法与JDBC中类似。
Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。

 

JDBC的事务管理

     JDBC的一切行为包括事务是基于一个connection的,在JDBC中是通过Connection对象进行事务管理的,默认是自动提交事务,可以手工将自动提交关闭,通过commit方法进行提交,rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。
    

 基于J2EE分层架构设计思想,数据访问层应该专门处理数据访问,而业务逻辑则在业务逻辑层中处理。为了提高复用,数据访问层对象(DAO)的粒度通常都非常小,一个更新操作被封装在一个方法中,这样当有多个更新操作需要被捆绑为一个事务的时候,事务的处理只能在业务逻辑层中实现。
在不分层的情况下,一个典型的JDBC事务处理代码片断如下。
try {
conn =DriverManager.getConnection  
("jdbc:oracle:thin:@host:1521:SID","username","userpwd";
conn.setAutoCommit(false);//禁止自动提交,设置回滚点
stmt = conn.createStatement();
stmt.executeUpdate(“alter table …”); //数据库更新操作1
stmt.executeUpdate(“insert into table …”); //数据库更新操作2
conn.commit(); //事务提交
}catch(Exception ex) {  
         ex.printStackTrace();
         try {
              conn.rollback(); //操作不成功则回滚
         }catch(Exception e) {
e.printStackTrace();
         }
}

JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:

public void setAutoCommit(boolean)
public boolean getAutoCommit()
public void commit()
public void rollback()

使用 JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。

JDBC的事务管理的安全性及效率分析

        如果直接使用基本的JDBC connection,肯定是关掉连接最安全。如果所有代码共用一个连接,会有效率问题,有时还会死锁、connection不是线程安全的。
       用不用DataSource跟关不关Connection没直接关系。 用DataSource只是把Connection的创建解离出来,可以变化。 DataSource是个接口,连接池是利用这个接口,返回一个Connection的代理(或者Wrapper,Delegate之类), 在调用这个代理的close方法时,不是直接关闭,而是把Connection放回连接池。
       同时,因为需要事务需要保证使用一个连接, 而且如果每次调用 Dao都简单从DataSource建立连接, 不能保证连接一致,效率也会有些问题。 因此,比较好的做法是利用ThreadLocal,调用统一方法建立连接,该方法先检查ThreadLocal里有没有连接,有则利用, 没有则新建,连接放到ThreadLocal里。
      Spring的DataSourceUtil是怎么写的,就是那个思路。ThreadLocal不是Connection的封装,而是Connection的保存点。 用连接池并不能保证你用的Connection是按线程一致的。 一般的连接池实现并不关心这点。
      使用事务管理代码,在事务开始时,向连接池请求连接, 之后Dao不是直接向连接池请求连接而是获取ThreadLocal中的Connection, 在事务结束后,提交事务,关闭Connection(如果使用连接池,则将Connection返还给事务) 所以必须保证有事务提交和Connection关闭代码。 所以Spring的例子代码,一般是把事务管理放在Service层,而不是Dao层。

 

 

JTA的事务管理

     Java事务API(JTA;Java Transaction API)J2EE平台提供了分布式事务服务。一个分布式事务(distributed transaction)包括一个事务管理器(transaction manager)和一个或多个资源管理器(resource manager)。一个资源管理器(resource manager)是任意类型的持久化数据存储。事务管理器(transaction manager)承担着所有事务参与单元者的相互通讯的责任。下图显示了事务管理器和资源管理的间的关系。

    JTA 事务
 JTA (Java Transaction API) 为 J2EE 平台提供了分布式事务服务。
 要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。例如:
 import javax.transaction.*;
 import javax.naming.*;
   // ...
   InitialContext ctx = new InitialContext();
   Object txObj = ctx.lookup(";java:comp/UserTransaction";);
   UserTransaction utx = (UserTransaction) txObj; 

  应用程序有了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()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了, 别的都是黑箱操作。
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、付费专栏及课程。

余额充值