我正在尝试使用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>
数据源创建如下
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 Database 10g之前的所有版本中,从XAConnection获取的连接上的默认自动提交状态为false。从Oracle Database 10g开始,默认状态为true。”
我使用的是Oracle 11g r2。知道在使用分布式事务将自动提交状态设置为false时应该进行哪些配置更改?
更新3
如果我使用bitronix池数据源而不是oracle ucp PoolDataSource,则事务有效。使用bitronix PoolingDataSource为bitronix提供了将自动提交状态设置为false的机会。将调查更多来计算两者之间的差异。
据我所知,它们是在交易中执行的,但交易并不是您所期望的。当autoCommit
是true
时,每个查询都成为一个事务。您必须正确配置连接以避免这种情况。
也就是说,关于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
是否已包含类似的内容,但显然它没有。