提交 8a3424e2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 321: the database does not expect XA rollback without XA prepare (an…

Issue 321: the database does not expect XA rollback without XA prepare (an exception was unnecessarily written into the .trace.db file).
上级 70862ee8
......@@ -45,6 +45,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
private volatile Connection handleConn;
private ArrayList<ConnectionEventListener> listeners = New.arrayList();
private Xid currentTransaction;
private boolean prepared;
static {
org.h2.Driver.load();
......@@ -200,6 +201,9 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
rs.close();
Xid[] result = new Xid[list.size()];
list.toArray(result);
if (list.size() > 0) {
prepared = true;
}
return result;
} catch (SQLException e) {
XAException xa = new XAException(XAException.XAER_RMERR);
......@@ -229,6 +233,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
try {
stat = physicalConn.createStatement();
stat.execute("PREPARE COMMIT " + JdbcXid.toString(xid));
prepared = true;
} catch (SQLException e) {
throw convertException(e);
} finally {
......@@ -247,6 +252,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
if (isDebugEnabled()) {
debugCode("forget("+JdbcXid.toString(xid)+");");
}
prepared = false;
}
/**
......@@ -262,15 +268,16 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
try {
physicalConn.rollback();
physicalConn.setAutoCommit(true);
if (prepared) {
Statement stat = null;
try {
stat = physicalConn.createStatement();
stat.execute("ROLLBACK TRANSACTION " + JdbcXid.toString(xid));
} catch (SQLException e) {
// ignore (not a two phase commit)
} finally {
JdbcUtils.closeSilently(stat);
}
prepared = false;
}
} catch (SQLException e) {
throw convertException(e);
}
......@@ -295,6 +302,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
if (!currentTransaction.equals(xid)) {
throw new XAException(XAException.XAER_OUTSIDE);
}
prepared = false;
}
/**
......@@ -324,6 +332,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
throw convertException(e);
}
currentTransaction = xid;
prepared = false;
}
/**
......@@ -344,6 +353,7 @@ public class JdbcXAConnection extends TraceObject implements XAConnection, XARes
} else {
stat = physicalConn.createStatement();
stat.execute("COMMIT TRANSACTION " + JdbcXid.toString(xid));
prepared = false;
}
physicalConn.setAutoCommit(true);
} catch (SQLException e) {
......
......@@ -7,13 +7,14 @@
package org.h2.test.jdbcx;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
......@@ -36,6 +37,7 @@ public class TestXA extends TestBase {
}
public void test() throws Exception {
testRollbackWithoutPrepare();
testXAAutoCommit();
deleteDb("xa");
testMixedXaNormal();
......@@ -48,6 +50,40 @@ public class TestXA extends TestBase {
deleteDb(DB_NAME2);
}
private void testRollbackWithoutPrepare() throws Exception {
Xid xid = new Xid() {
public int getFormatId() {
return 3145;
}
public byte[] getGlobalTransactionId() {
return new byte[] { 1, 2, 3, 4, 5, 6, 6, 7, 8 };
}
public byte[] getBranchQualifier() {
return new byte[] { 34, 43, 33, 3, 3, 3, 33, 33, 3 };
}
};
deleteDb("xa");
JdbcDataSource ds = new JdbcDataSource();
ds.setURL(getURL("xa", true));
Connection dm = ds.getConnection();
Statement stat = dm.createStatement();
stat.execute("CREATE TABLE IF NOT EXISTS TEST(ID INT PRIMARY KEY, VAL INT)");
stat.execute("INSERT INTO TEST(ID,VAL) VALUES (1,1)");
dm.close();
XAConnection c = ds.getXAConnection();
XAResource xa = c.getXAResource();
Connection connection = c.getConnection();
xa.start(xid, XAResource.TMJOIN);
PreparedStatement ps = connection.prepareStatement("UPDATE TEST SET VAL=? WHERE ID=?");
ps.setInt(1, new Random().nextInt());
ps.setInt(2, 1);
ps.close();
xa.rollback(xid);
connection.close();
c.close();
deleteDb("xa");
}
private void testMixedXaNormal() throws Exception {
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:mem:test");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论