trzxycx 发表于 2017-2-16 10:04:46

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();
}
}
}
页: [1]
查看完整版本: JTA 在Weblogic中的使用实例