原文链接:
http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html?page=3
Page 3 of 6
@Transactional @Test public void testInsertIntoTwoDataSources() throws Exception { int count = getJdbcTemplate().update( "INSERT into T_FOOS (id,name,foo_date) values (?,?,null)", 0, "foo"); assertEquals(1, count); count = getOtherJdbcTemplate() .update( "INSERT into T_AUDITS (id,operation,name,audit_date) values (?,?,?,?)", 0, "INSERT", "foo", new Date()); assertEquals(1, count); // Changes will roll back after this method exits }上述操作在发生更新错误的时候,函数退出时会执行数据回滚。
然后MulipleDataSourceTests
检查两个操作是否都被回滚,如列表2所示:
@AfterTransaction public void checkPostConditions() { int count = getJdbcTemplate().queryForInt("select count(*) from T_FOOS"); // This change was rolled back by the test framework assertEquals(0, count); count = getOtherJdbcTemplate().queryForInt("select count(*) from T_AUDITS"); // This rolled back as well because of the XA assertEquals(0, count); }为了更好的理解Spring事务管理是如何工作以及如何配置的,请查阅Spring参考指南( Spring Reference Guide)。
这个模式是一个优化方案,很多事务管理器用来避免如果事务只包含单个资源的时候,两阶段提交(2PC)所带来的过度开销,应用服务器需要能判断出这种情况。
很多XA事务管理器的另外一个特性是,对于除了一个资源外所有其他资源均为XA兼容的情况,它们同样能提供和全部为XA资源一样的故障恢复保证。这是通过资源排序以及使用非XA资源做为最后的决定性投票。如果它提交失败, 那么所有其他资源可以被回滚。这和100%的无漏洞(bulletproof)模式很接近 -- 但不完全是。而且当它失败时,不会留下太多跟踪信息,除非采用额外的措施(如同一些高端解决方案所实现的那样)。
在一些系统中,一个很好的可以降低复杂性以及提高吞吐量的模式是通过确保所有的事务资源都被同一个资源所支持,从而完全移除对XA的使用依赖。这显然不是一个所有场景都适用的通用模式,但和XA一样健壮而且快得多。分享式事务资源模式是无漏洞的(bulletproof),但是仅适用于特定的平台和处理场景。
关于这个模式,一个简单的,很多人都熟悉的例子是,在一个使用ORM的组件和一个使用JDBC组件之间共享数据库连接。这通常发生在当你使用支持一些ORM工具比如Hibernate, EclipseLink,以及Java Persistence API (JPA)的Spring事务管理器的时候。同样的事务可以安全的跨越于ORM和JDBC组件之间,通常由上面的控制事务的服务层方法所驱动。
另外一个有效使用该模式的例子是基于消息驱动的单个数据库更新(如同本文介绍中所举的例子一样)。消息中间件系统需要存储它们的数据在某个地方,通常是一个关系型数据库。为实现给模式,所需要的只是为消息系统指定业务数据将使用同一个数据库。这个模式依赖于消息中间件供应商暴露其存储策略的细节,这样可以把消息中间件配置为指向统一的数据库和挂靠到相同的事务。
by iefreer