在复杂的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();
}
}
}
分享到:
相关推荐
实例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 ...
但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 21、...
但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理, EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 24、...
Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 设定字符串为“张三,你好,我是李四” 产生张三的密钥对(keyPairZhang) 张三生成公钥(publicKeyZhang...
这里边包括:第1章 Java图形用户界面编程 1 实例1 布局管理 2 实例2 设计软件启动界面 9 实例3 实现多色窗口 11 实例4 切分窗口 13 实例5 丰富多彩的按钮 15 实例6 在窗口中显示背景图 16 实例...
Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 设定字符串为“张三,你好,我是李四” 产生张三的密钥对(keyPairZhang) 张三生成公钥(publicKeyZhang...
76.4. 在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中? 86 76.5. 在weblogic中发布ejb需涉及到哪些配置文件 87 76.6. 如何在weblogic中...
9) aa.jsp与bb.jsp属于同一应用,在aa.jsp中使用标记,在bb.jsp中要把beanName这个bean对象变量所引用的对象取出来。那么对于以下描述,正确的是: c a) 在bb.jsp中仅使用代码:mybean bc = session....
JSP JSP与服务程序 JSP与ASP 实现JSPs JavaServer Page范例 JavaBeans综述 在JSPs中使用JavaBeans JSP事宜 资源 小结 第16章 使用JSP进行数据访问 访问数据 范例应用程序 ...