Transactions 在mySql和Oracle不工作的情况下使用atomikos的分布式事务(XA)

Transactions 在mySql和Oracle不工作的情况下使用atomikos的分布式事务(XA),transactions,spring-transactions,xa,atomikos,Transactions,Spring Transactions,Xa,Atomikos,我正在尝试测试分布式/XA事务。 我在使用mySql、Oracle、Atomikos和spring 没有使用应用程序服务器-因此请不要向我指出应用程序服务器解决方案 在事务中-我首先尝试更新Oracle表 然后在同一事务中,am尝试插入MySql 我正在确保插入由于表上的唯一约束而失败。 理想情况下,由于mysql不成功,Oracle更新也应该回滚,但这似乎没有发生,Oracle表更新是基于sysdate进行的。 下面是完整的代码: spring配置文件: <bean id="userTr

我正在尝试测试分布式/XA事务。
我在使用mySql、Oracle、Atomikos和spring
没有使用应用程序服务器-因此请不要向我指出应用程序服务器解决方案

在事务中-我首先尝试更新Oracle表
然后在同一事务中,am尝试插入MySql
我正在确保插入由于表上的唯一约束而失败。
理想情况下,由于mysql不成功,Oracle更新也应该回滚,但这似乎没有发生,Oracle表更新是基于sysdate进行的。
下面是完整的代码:
spring配置文件:

<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
    init-method="init" destroy-method="shutdownForce">
    <constructor-arg>
        <props>
            <prop key="com.atomikos.icatch.service">
                com.atomikos.icatch.standalone.UserTransactionServiceFactory
            </prop>
            <prop key="com.atomikos.icatch.tm_unique_name">myname</prop>
            <prop key="com.atomikos.icatch.log_base_name">myLogName</prop>
            <prop key="com.atomikos.icatch.log_base_dir">xyz/atomikos</prop>
            <prop key="com.atomikos.icatch.checkpoint_interval">100</prop>
            <prop key="com.atomikos.icatch.console_file_count">2</prop>
            <prop key="com.atomikos.icatch.max_timeout">300000</prop>
            <prop key="com.atomikos.icatch.max_actives">128</prop>
        </props>
    </constructor-arg>  
</bean>

<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close" depends-on="userTransactionService">
    <property name="startupTransactionService" value="false" />
    <property name="forceShutdown" value="false" />
</bean>

<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
    depends-on="userTransactionService">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="jtaTxManager"
    class="org.springframework.transaction.jta.JtaTransactionManager"
    depends-on="userTransactionService">
    <property name="transactionManager" ref="AtomikosTransactionManager" />
    <property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>

<bean id="myTxTest" class="com.runner.MyTxTester">      
    <property name="oraUpdater" ref="myOraUpdater" />
    <property name="mySqlInserter" ref="mySqlInserter" />
    <property name="txManager" ref="jtaTxManager" />
</bean>

<bean id="mySqlInserter" class="com.xyz.dao.MySqlInserter">
    <property name="sql"
        value="insert into person (name,country) values ('abc','USA');" />
    <property name="dataSource" ref="MySqldataSource" />
</bean>

<bean id="myOraUpdater" class="com.xyz.dao.OraUpdater">
    <property name="sql"
        value="UPDATE PurchaseOrders SET LAST_UPDATE=SYSDATE" />
    <property name="dataSource" ref="OraDataSource" />
</bean>

<bean id="OraDataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" lazy-init="true">
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
    <property name="username" value="TEST1" />
    <property name="password" value="TEST11" />
    <property name="driverClassName" value="oracle.jdbc.xa.client.OracleXADataSource" />        
</bean>

<bean id="MySqldataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" lazy-init="true">
    <property name="url" value="jdbc:mysql://localhost/test2" />
    <property name="username" value="test2" />
    <property name="password" value="test2" />
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />       
</bean>
调用对象的类:

public class MyTxTester {
private final SQLErrorCodeSQLExceptionTranslator exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator();
private PlatformTransactionManager txManager;
private DBUpdater<SqlParameterSource> oraUpdater;
private DBUpdater<SqlParameterSource> mySqlInserter;

public void wrapperCall(){      
    TransactionTemplate txTemplate = new TransactionTemplate(txManager);
    txTemplate.execute(new TransactionCallback<Object>() {
        public Object doInTransaction(TransactionStatus transactionStatus) {
            try {
                //do oracle update
                doOraUpdate();
                //do mysql insert   
                doMySqlInsert();
            } catch (Exception sqle) {
                throw exceptionTranslator.translate("SQLException ","abc", new SQLException());
            }   
            return null;
        }
    });
}

public void doOraUpdate(){
    System.out.println(" first going for Oracle update ");
    getOraUpdater().update();
}

public void doMySqlInsert(){
    System.out.println(" second going for mySql insert ");
    getMySqlInserter().insert();
}
公共类MyTxTester{
私有最终SQLErrorCodeSQLExceptionTranslator exceptionTranslator=新SQLErrorCodeSQLExceptionTranslator();
私有平台TransactionManager txManager;
私有数据库更新程序或更新程序;
私有数据库更新程序mySqlInserter;
public void wrapperCall(){
TransactionTemplate txTemplate=新的TransactionTemplate(txManager);
execute(新TransactionCallback(){
公共对象doInTransaction(TransactionStatus TransactionStatus){
试一试{
//做oracle更新吗
doOraUpdate();
//是否插入mysql
doMySqlInsert();
}捕获(sqle异常){
抛出exceptionTranslator.translate(“SQLException”,“abc”,newSQLException());
}   
返回null;
}
});
}
公共门户更新(){
System.out.println(“第一次进行Oracle更新”);
getOraUpdater().update();
}
public void doMySqlInsert(){
System.out.println(“mySql插入的第二步”);
getMySqlInserter().insert();
}
道类-

public class OraUpdater<E extends SqlParameterSource>  {

/** The data source. */
private DataSource dataSource;

/** The jdbc template. */
private NamedParameterJdbcTemplate jdbcTemplate;

/** The sql. */
private String sql;

public Object update()  {
    SqlParameterSource paramSource = null;
    getJdbcTemplate().update(getSql(), paramSource);
    return null;
}
公共类更新程序{
/**数据源*/
私有数据源;
/**jdbc模板*/
私有名称参数jdbcTemplate jdbcTemplate;
/**sql*/
私有字符串sql;
公共对象更新(){
SqlParameterSource paramSource=null;
getJdbcTemplate().update(getSql(),paramSource);
返回null;
}
MySqlDao:

public class MySqlInserter<E extends SqlParameterSource>  {

/** The data source. */
private DataSource dataSource;

/** The jdbc template. */
private NamedParameterJdbcTemplate jdbcTemplate;

/** The sql. */
private String sql;

public Object insert()  {
    SqlParameterSource paramSource = null;
    getJdbcTemplate().update(getSql(), paramSource);
    return null;
}
公共类MySqlInserter{
/**数据源*/
私有数据源;
/**jdbc模板*/
私有名称参数jdbcTemplate jdbcTemplate;
/**sql*/
私有字符串sql;
公共对象插入(){
SqlParameterSource paramSource=null;
getJdbcTemplate().update(getSql(),paramSource);
返回null;
}

因此,不确定我缺少什么来确保原子性?

dbcp.BasicDatasource不支持XA。相反,需要使用dbcp.BasicManagedDatasource。此外,请确保还设置了XADataSource属性。

@mdeinum如果可以,请在此提供帮助
public class MySqlInserter<E extends SqlParameterSource>  {

/** The data source. */
private DataSource dataSource;

/** The jdbc template. */
private NamedParameterJdbcTemplate jdbcTemplate;

/** The sql. */
private String sql;

public Object insert()  {
    SqlParameterSource paramSource = null;
    getJdbcTemplate().update(getSql(), paramSource);
    return null;
}