spring分布式事务示例
资源管理器(如关系数据库)提供事务管理器和用于控制事务的API。 那些熟悉JDBC的人会知道,由于设置autocommit = true,默认情况下会启动事务。 每个更改数据库的语句都会自动提交。 可以通过将autocommit设置为false来更改此行为。 现在,程序员必须显式开始事务,然后提交或回滚该事务。
仅处理一种资源(例如一个数据库)的事务称为本地事务。 跨多个资源(例如多个数据库或一个数据库和一个消息传递引擎)的事务称为全局事务。 全局事务是使用XA协议实现的,该协议涉及两阶段提交。 JTA规范描述了Java API,供程序员使用全局事务。 JDBC中的事务方法(例如开始,提交,回滚)仅适用于JDBC和关系数据库,而JTA可以与任何事务资源一起使用。
但是,涉及事务的代码是可以由框架处理的样板代码。 在方法开始时,您需要开始一个事务,并且在方法完成时,您需要提交或回滚该事务。 如果您使用过EJB,可能会很熟悉,您可以在部署描述符中指定方法应在其中执行的事务环境。 例如,您可能会说RequiresNew,这意味着在调用该方法之前启动一个新事务。 容器在调用方法之前启动新事务,并在方法返回时提交新事务。 程序员不需要编写任何Java代码来处理事务。
在本文的其余部分,我们将通过一个示例讨论使用Spring进行声明式事务管理。
对于本教程,您将需要:
(1) Spring3.0
(2) Eclipse是可选的。 我使用eclipse作为我的IDE。 Eclipse使您可以导出可以部署到Tomcat的战争。 但是您也可以使用其他IDE或命令行工具。
(3)您可以从springjdbcwithTransaction.zip下载此示例的源代码。
我们重用了JDBC和Spring博客中的示例,这是我们之前写的。 让我们为MemberSpringJDBCDAO添加事务支持。 此类具有insertMember方法,该方法将成员插入数据库。 让我们稍微修改一下方法,以在插入数据库后抛出RuntimeException。 添加了运行时异常,以假装在更新数据库时业务逻辑中发生了错误。
public int insertMember(Member member) {JdbcTemplate jt = getJdbcTemplate() ;Object[] params = new Object[{member.getFirstname(),member.getLastname(),member.getStreet(),member.getCity(),member.getZip(),member.getEmail(),member.getPassword()} ;int ret = jt.update(insert_sql, params) ;throw new RuntimeException("simulate Error condition') ;return ret ;
}
在这种方法中,您是否希望将插入内容提交给数据库? 答案是肯定的,尽管这不是理想的行为。 JDBC的默认行为是autocommit = true,这意味着每个插入或更新都将立即提交。 您可以设置autocommit = false,并在方法末尾显式提交或回滚。 但是让您的容器处理此问题要容易得多。
要将声明式事务管理添加到上述方法中,请使用以下步骤:
步骤1:在springjdbcdao.xml中定义一个事务管理器
<bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>
Spring与事务管理器一起开始和完成事务。
步骤2:启用对交易注释的支持
添加到springjdbcdao.xml
<tx:annotation-driven transaction-manager="txManager"/>
步骤3:将@Transactional批注添加到insertMember方法
@Transactional
public int insertMember(Member member) {
...
@Transactional可以使用属性,但我们将使用以下默认值:
传播方式:必填
必需表示需要进行交易。 如果没有事务,Spring将请求事务管理器启动一个事务。 其他可能的值是Requires_New,它告诉事务管理器始终挂起现有事务并开始一个新事务。
隔离级别:默认
使用基础资源管理器的默认隔离级别。
回滚:任何运行时异常都会触发回滚
步骤4:使用Junit测试MemberSpringJDBCDAOTest运行更新的insertMember方法。
您将从事务管理器中看到以下日志,指示该事务已回滚。
org.springframework.jdbc.datasource.DataSourceTransactionManager –启动事务回滚
2501 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager –启动事务回滚
2501 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager –在Connection [org.apache.derby.impl.jdbc.EmbedConnection40@13320911(XID = 2827),(SESSIONID = 1),(DATABASE = c:\ manoj \ mjprojects \ database \ pumausers),(DRDAID = null)2501 [main]调试org.springframework.jdbc.datasource.DataSourceTransactionManager –在Connection [org.apache.derby.impl.jdbc]上回滚JDBC事务。 EmbedConnection40 @ 13320911(XID = 2827),(SESSIONID = 1),(数据库= c:\ manoj \ mjprojects \ database \ pumausers),(DRDAID = null)] 2511
使用SQL检查数据库表。 确认未添加任何记录。
步骤5:从insertMember方法中删除runtimeexception,然后再次运行测试。
Spring调试日志显示了事务已提交。 使用SQL检查数据库表。 确认记录已添加到表中。
总之,事务对于维护数据源的ACID属性是必需的。 使用Spring的声明式事务使该任务更加容易。
参考: The Khangaonkar报告中来自我们的JCG合作伙伴 Manoj的Spring和声明性交易 。
相关文章 :
- YouTube Java API入门
- Google Guava库必需品
- Java Code Geeks Andygene Web原型
- 使用Spring Security保护GWT应用程序的安全
翻译自: https://www.javacodegeeks.com/2011/09/spring-declarative-transactions-example.html
spring分布式事务示例