JTA-transaction

来源:互联网 发布:淘宝卖家设置发货时间 编辑:程序博客网 时间:2024/05/18 03:05
Java Transaction API,译为Java事务API。JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JTA主要用于分布式的多个数据源的两阶段提交的事务,而JDBC的Connection提供的单个数据源的事务; 后者因为只涉及到一个数据源,所以其事务可以由数据库自己单独实现, 而JTA事务因为其分布式和多数据源的特性, 不可能由任何"一个"数据源实现事务, 因此JTA中的事务是由"事务管理器"实现的,它会在多个数据源之间统筹事务,具体使用的技术就是所谓的"两阶段提交", 一般JTA事务都是用于EJB中(因为EJB本身也是分布式的), 所以一般的应用服务器都有自己的事务管理器用来管理JTA事务,注意这并不表示EJB容器有管理事务的功能; 事实上也有单独的事务管理器比如开源的Tyrex. 如果只用Tomcat做应用服务器的话是不能使用JTA事务的;JTA是J2EE规范,J2EE容器都支持,跟spring没有关系。tomcat不是J2EE容器,所以需要借助第三方的工具包才能实现。

使用 JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。
JTA 事务比 JDBC 事务功能更强。JDBC 事务局限为一个数据库连接,而 JTA 事务可以有多个参与者。所有下列 Java 平台组件都可以参与 JTA 事务:
JDBC 连接
JDOPersistenceManager 对象
JMS 队列
JMS 主题
企业 JavaBeans
符合 J2EE 连接体系结构(J2EE Connector Architecture)规范的资源适配器

使用 JTA 的事务界定
要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。
一个对 UserTransaction 对象的JDNI 查询
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();
当应用程序调用 commit()时,事务管理器用一个两阶段的提交协议结束事务。

如果计划用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource、javax.sql.XAConnection和 javax.sql.XAResource接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。XAConnections 是参与 JTA 事务的 JDBC 连接。
您将需要用应用服务器的管理工具设置 XADataSource。从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。
J2EE 应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象,它就调用javax.sql.DataSource.getConnection() 以获得到数据库的连接。
XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时,应用程序一定不要对 XA 连接调用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback()。相反,应用程序应该使用 UserTransaction.begin()、UserTransaction.commit() 和 serTransaction.rollback()。

JTA 在Weblogic中的使用实例
1,通过JNDI得到TransactionManager,然后可以用TransactionManager的begin,commit等方法来控制事务.
traMgr = (TransactionManager) context.lookup("javax.transaction.UserTransaction");
2,获取在weblogic上定义的datasource,datasource必须支持XA.
DataSource ds1 = (DataSource)context.lookup("DSORCL");
3,用TransactionManager声明事务开始,通过DataSource操作数据库,然后commit或者rollback事务.
traMgr.begin();
...//通过DataSource得到connection,然后操作数据库.
traMgr.commit();或者traMgr.rollback();
有时候,数据源可能不是在weblogic上配置的,或者是从不同的APP server上获取的(不过这种情况一般比较少).需要利用TransactionManager.enlistResource(XAResource)主动的把这种资源加入到当前的事务管理中来.而对于从 weblogic上配置的DataSource,TransactionManager声明事务后,DataSource可以自动的发现并加入当前的事务.TransactionManager在begin()的时候会将当前的事务信绑定到当前的线程上.

public class TraMgrExample {   
    public void executeTra1(Connection conn) throws SQLException{  
        PreparedStatement pstmt = conn.prepareStatement("Insert into A values(3,'VAL1')");             
        pstmt.executeUpdate();  
        pstmt.close();  
    }  
    public void executeTraOutWlS(Connection conn ) throws SQLException{  
        PreparedStatement pstmt = conn.prepareStatement("Insert into B values(1,'TRANSACTION MANAGER TEST')");             
        pstmt.executeUpdate();  
        pstmt.close();  
    }  
 
    public void testGlobalTransaction() {
        TransactionManager traMgr = null;  
        Connection conn1 = null;  
        Connection conn2 = null;  
        try {                 
            Context context = new InitialContext();  
            DataSource ds1 = (DataSource)context.lookup("DSORCL");  
            System.out.println("ds1." + ds1);  
            conn1 = ds1.getConnection();  
            conn1.setAutoCommit(false);
            traMgr = (TransactionManager) context.lookup("javax.transaction.UserTransaction");
            traMgr.begin();         
            XADataSource xads1 = getXADS1();//这个数据源是通过JDBC配置的  
            XAConnection xaConn1 = xads1.getXAConnection();  
            XAResource xaRes1 = xaConn1.getXAResource();     
            traMgr.getTransaction().enlistResource(xaRes1);//需要主动的加入到当前的事务中         
            conn2 = xaConn1.getConnection();  
            conn2.setAutoCommit(false);  
            executeTraOutWlS(conn2);   
            executeTra1(conn1);//通过在weblogic上配置的DataSource,会自动加入到当前的事务中.   
            traMgr.commit();
        } catch (Exception e) {      
            try {  
                traMgr.rollback();  
                System.out.println("Exception happened, roll back all the transactions managed by traMgr.");  
            } catch (IllegalStateException e1) {  
                e1.printStackTrace();  
            } catch (SecurityException e1) {  
                e1.printStackTrace();  
            } catch (SystemException e1) {  
                e1.printStackTrace();  
            }       
            e.printStackTrace();  
        }finally{  
            try {  
                conn1.close();  
                conn2.close();    
            } catch (SQLException e) {  
                e.printStackTrace();  
            }       
        }  
    }  
 
    public XADataSource getXADS1() throws SQLException {  
        OracleXADataSource oxaDS = new OracleXADataSource();  
        oxaDS.setDatabaseName("ORCL");  
        oxaDS.setServerName("localhost");  
        oxaDS.setPortNumber(1521);  
        oxaDS.setUser(DemoConstant.UID);  
        oxaDS.setPassword(DemoConstant.PWD);  
        oxaDS.setURL("jdbc:oracle:thin:@localhost:1521:ORCL");  
        return oxaDS;  
    }
}



原创粉丝点击