如何解决使用Oracle JDBC驱动程序进行Spring XA事务
|| 我正在尝试使用bitronix事务管理器启用分布式事务。配置详细信息包括 使用OCI JDBC驱动程序和oracle.jdbc.xa.client.OracleXADataSource。此数据源由UCP连接池数据源包装-oracle.ucp.jdbc.PoolDataSourceImpl 使用spring JdbcTemplate执行查询。 使用Bitronix交易管理器处理分布式交易 使用注释的Spring声明式事务 我面临的问题是使用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开发人员指南》提到
\“从XAConnection获得的连接上的默认自动提交状态在Oracle Database 10g之前的所有发行版中均为false。从Oracle Database 10g开始,默认状态为true。\”
我正在使用Oracle 11g r2。知道使用分布式事务将自动提交状态设置为false时应进行哪些配置更改?
更新3
如果使用bitronix池数据源而不是oracle ucp PoolDataSource,则事务有效。使用bitronix的PoolingDataSource为bitronix提供了将自动提交状态设置为false的机会。将进行更多的调查以找出两者之间的区别。
解决方法
您是否有包含此代码的方法,该方法带有@Transactional批注或定义了任何方面,这些方面将告诉Spring在事务中执行此方法?
,据我所知,它们在事务中执行,但是事务不是您所期望的。当autoCommit
是true
时,每个查询都成为一个事务。您必须正确配置连接以避免这种情况。
就是说,有关XA的评论:XA在诸如网络问题和超时之类的极端情况下不起作用。也就是说,它将工作99.9995%次,但是在某些关键情况下,它将无法正常工作,而这正是您关心的情况。
确保当XA最终使您失败时,您的数据结构不会损坏。
建议不要使用XA,而是评估允许再次运行事务的方法。示例:您想将某些记录从数据库A传输到B。因此,您读取带有ѭ5the的行,并为每个传输的行将processed
列设置为true。
另一方面,您只需添加尚不存在的行。
提交B中的tx之后,删除Awhere processed = \'true\'
中的行或以其他方式标记它们。
这意味着您可以根据需要多次运行它。
[编辑]
要禁用自动提交,您必须调用ѭ8。当然,问题是您使用的是Spring,因此您从不明确要求在任何地方进行连接。
我的建议:扩展ѭ9并覆盖各种get*Connection()
方法。返回它们之前,请将auto commit设置为false。您还可以反编译JDBC驱动程序代码,以查看PoolDataSourceImpl
是否已包含类似内容,但显然没有。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。