2011-05-26 104 views
0

我试图使用bitronix事务管理器启用分布式事务。配置详细信息包括:Spring XA事务与Oracle JDBC驱动程序

  1. 使用OCI JDBC驱动程序和oracle.jdbc.xa.client.OracleXADataSource。此数据源由UCP连接池数据源环绕 - oracle.ucp.jdbc.PoolDataSourceImpl
  2. 使用Spring JdbcTemplate执行查询。
  3. 使用Bitronix事务管理器使用注解

我现在面临的问题是,使用的JdbcTemplate执行的查询未在交易被执行处理的分布式事务

  • 春天声明性事务。我的测试用例使用JDBCTemplate执行两个查询,并且在查询执行后该方法抛出运行时异常时它们不会回滚。我也可以看到连接的自动提交状态设置为true。

    <tx:annotation-driven transaction-manager="distributedTransactionManager"/> 
    
    <bean id="distributedTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
        <property name="transactionManager" ref="bitronixTransactionManager"/> 
        <property name="userTransaction" ref="bitronixTransactionManager"/> 
        <property name="allowCustomIsolationLevels" value="true"/> 
    </bean> 
    
    <bean id="bitronixTransactionManager" factory-method="getTransactionManager" 
         class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfiguration" 
         destroy-method="shutdown"> 
    </bean> 
    

    The data source is created as follows

    PoolDataSourceImpl pds = new PoolDataSourceImpl(); 
        try { 
         pds.setConnectionPoolName(dataSourceName); 
         pds.setConnectionFactoryClassName("oracle.jdbc.xa.client.OracleXADataSource"); 
         pds.setConnectionFactoryProperties(getOracleDataSourceProperties()); 
         pds.setDataSourceName(dataSourceName); 
         pds.setServerName("v-in-sd-tst-12"); 
         pds.setPortNumber(1521); 
         pds.setUser("ForTestCasesAmit"); 
         pds.setPassword("adept"); 
         pds.setMinPoolSize(10); 
         pds.setMaxPoolSize(100); 
         pds.setMaxIdleTime(1800); 
    
         pds.startPool(); 
        } catch (SQLException e) { 
         throw new RuntimeException("Cannot create project datasource " + dataSourceName, e); 
        } 
        return pds; 
    

    上,这可能是为什么查询不在事务中执行的原因有什么建议?

    更新1

    添加,其执行使用的JdbcTemplate查询和在末端抛出异常的方法

    @Transactional(propagation = Propagation.REQUIRED) 
    public void execute() { 
        System.out.println("Starting with the service method"); 
        jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Date1' WHERE COL2 = 1"); 
    
        jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Start Date1' WHERE COL2 = 2"); 
    
        waitForUserInput(); 
        throw new RuntimeException("Rollback Now"); 
    } 
    

    更新2

    Oracle JDBC Developer Guide提到

    “在Oracle数据库10g之前的所有版本中,从XAConnection获取的连接上的默认自动落实状态为false。从Oracle数据库10g开始,默认状态是真实的。”

    我使用Oracle 11g R2。任何想法配置更改应该而使用分布式事务进行有自动提交状态为假?

    更新3

    的交易,如果我使用bitronix汇集的数据源,而不是甲骨文UCP PoolDataSource工作。使用bitronix PoolingDataSource给了一个机会bitronix到自动提交状态设置为false。将调查更推测两者之间的区别。

  • 回答

    0

    您是否拥有包含此代码的方法,用@Transactional注释或定义了任何方法,这些方法会告诉Spring在事务中执行此方法?

    +0

    我已经用spring注释的方法更新了这个问题。 – 2011-05-26 08:58:11

    0

    据我所知,他们在交易中执行,但交易不是你所期望的。当autoCommittrue时,每个查询都成为一个事务。您必须正确配置连接才能避免这种情况。

    也就是说,有关XA:XA的评论在网络问题和超时等极端情况下不起作用。也就是说,它会工作99。9995%次,但在一些危急情况下,它不会,这些都是你关心的情况。

    确保您的数据结构在XA最终失败时不会损坏。

    而不是XA,我建议评估允许再次运行事务的方法。示例:您想要将一些记录从数据库A传输到B.因此,您读取的行数为FOR UPDATE,对于每个传输的行,您将processed列设置为true。

    另一方面,您只能添加不存在的行。

    在B中的tx已被提交后,删除A where processed = 'true'中的行或以其他方式标记它们。

    这意味着您可以根据需要随时运行此操作。

    [编辑]

    要禁用自动提交,你必须调用con.setAutoCommit(false);的问题是,当然,前提是你使用Spring,所以你永远不会明确要求连接的任何地方。

    我的建议:扩展PoolDataSourceImpl并覆盖各种get*Connection()方法。在返回它们之前,将auto commit设置为false。您也可以反编译JDBC驱动程序代码以查看PoolDataSourceImpl是否已经包含类似的内容,但显然不是。

    +0

    好的。你有没有建议/理由为什么这两个查询不会回滚,即使交易应用到它?更重要的是当抛出运行时异常时我应该做什么配置更改回滚? – 2011-05-26 12:22:57

    +0

    因为在发出'commit'后没有发生回滚。会发生什么是'q1;承诺; Q2;承诺;抛出异常; rollback'。要更改autoCommit,请检查创建连接的代码。在你的情况下,'PoolDataSourceImpl'应该有一个方法。 – 2011-05-26 13:04:27

    +0

    是的。我知道自动提交设置为true,因此回滚没有发生。我提出这个问题的目的是要知道是否有人尝试过使用上述配置的分布式事务,以及我错过了哪些更精细的细节。 – 2011-05-26 14:16:40