`

JTA 在Weblogic中的使用实例

 
阅读更多

在复杂的J2EE应用中,如果涉及到要在一个事务中将数据保存到多个数据库,或者在一个事务中同时要操作数据库资源和JMS资源,为了保证数据在多个参入的数据源中的一致性,就需要用到JTA来控制事务,参入的数据源也需要支持X/Open协议(两阶段提交).

本文简单介绍如何在weblogic中使用JTA和解释JTA的TransactionManager是怎么定义事务边界和提交回滚事务的.

JTA的使用:

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() {
System.out.println("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");
System.out.println("traMgr." + traMgr);

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();


System.out.println("finished.");

} 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;
}

}

weblogic的JTA主要是通过候将当前事务绑定到线程来达到TransactionManager和DataSource之间的协调的.下面通过一些JAVA代码来模拟这中协调.主要是演示线程绑定,对于两阶段提交,恢复和一些细节没有做考虑.

1,下面这两个类负责保存和线程相关的Connection:(weblogic是通过InheritableThreadLocal来保存线程相关的事务信息)

public class JTAInfo {
private static Map<Thread,JTAConnections> jtaInfo = new HashMap<Thread,JTAConnections>();
public static Map<Thread, JTAConnections> getJtaInfo() {
return jtaInfo;
}
public static void setJtaInfo(Map<Thread, JTAConnections> jtaInfo) {
jtaInfo = jtaInfo;
}
}

public class JTAConnections {
private List<Connection> connections = new ArrayList<Connection>();
public List<Connection> getConnections() {
return connections;
}
public void setConnections(List<Connection> connections) {
this.connections = connections;
}
}

2,下面这个类模拟weblogic提供的DataSource:

public class XADataSource {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static Connection getConnection(String sid, String uid, String pwd) throws SQLException {
Connection conn = DriverManager.getConnection("jjdbc:oracle:thin:@localhost:1521:" + sid, uid, pwd);
conn.setAutoCommit(false);
//每次获取连接的时候,把这个connectin和当前的事务关联起来
JTAInfo.getJtaInfo().get(Thread.currentThread()).getConnections().add(conn);

return conn;
}
}

3,下面这个类模拟TransactionManager:


public class TransactionManager {
public void begin() {
if (JTAInfo.getJtaInfo().get(Thread.currentThread()) == null) {
JTAInfo.getJtaInfo().put(Thread.currentThread(), new JTAConnections());
}
}
public void enlistResource(Connection conn) {
JTAConnections jtaConnes = JTAInfo.getJtaInfo().get(Thread.currentThread());
jtaConnes.getConnections().add(conn);
}
public void commit() throws Exception {
List<Connection> connections = JTAInfo.getJtaInfo().get(Thread.currentThread()).getConnections();
try {
for (Connection conn : connections) {
conn.commit();
}
} finally {
try {
for (Connection conn : connections) {
conn.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void rollback() throws Exception {
List<Connection> connections = JTAInfo.getJtaInfo().get(Thread.currentThread()).getConnections();
try {
for (Connection conn : connections) {
conn.rollback();
}
} finally {
try {
for (Connection conn : connections) {
conn.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

4,一个使用这个模拟的客户端代码:


public class Main {
public static void tra1() throws Exception {
Connection conn = XADataSource.getConnection("ORCL", "yorker", "yorker");
Statement sta = conn.createStatement();
sta.executeUpdate("INSERT INTO A VALUES(1,'val1')");
sta.close();
}
public static void tra2() throws Exception {
Connection conn = XADataSource.getConnection("ORCL", "yorker", "yorker");
Statement sta = conn.createStatement();
sta.executeUpdate("INSERT INTO B VALUES(2,'val2')");
sta.close();
}
public static void main(String[] args) {
TransactionManager trMgr = new TransactionManager();

trMgr.begin();
try {
tra1();

tra2();
//trMgr.enlistResource(conn);//如果不是从模拟的datasource获取的连接,可以显示的加入到当前事务.

trMgr.commit();

} catch (Exception e) {

try {
trMgr.rollback();
} catch (Exception e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
}
}

分享到:
评论

相关推荐

    h_JAVA 2应用编程150例.rar

    实例118 使用JTA与JTS 417 实例119 Request-Reply模式的JMS应用 421 实例120 使用Java IDL 426 实例121 EJB与CORBA的交互 430 实例122 基于EJB的真实世界模型 433 实例123 EJB的商业应用——定购单 447 第11章 Java ...

    java 面试题 总结

    但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 21、...

    超级有影响力霸气的Java面试题大全文档

    但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理, EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 24、...

    JAVA上百实例源码以及开源项目源代码

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java应用软件程序设计

    这里边包括:第1章 Java图形用户界面编程 1 实例1 布局管理 2 实例2 设计软件启动界面 9 实例3 实现多色窗口 11 实例4 切分窗口 13 实例5 丰富多彩的按钮 15 实例6 在窗口中显示背景图 16 实例...

    JAVA上百实例源码以及开源项目

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java面试题

    76.4. 在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中? 86 76.5. 在weblogic中发布ejb需涉及到哪些配置文件 87 76.6. 如何在weblogic中...

    J2EE面试题

    9) aa.jsp与bb.jsp属于同一应用,在aa.jsp中使用标记,在bb.jsp中要把beanName这个bean对象变量所引用的对象取出来。那么对于以下描述,正确的是: c a) 在bb.jsp中仅使用代码:mybean bc = session....

    Java数据编程指南

    JSP JSP与服务程序 JSP与ASP 实现JSPs JavaServer Page范例 JavaBeans综述 在JSPs中使用JavaBeans JSP事宜 资源 小结 第16章 使用JSP进行数据访问 访问数据 范例应用程序 ...

Global site tag (gtag.js) - Google Analytics