声明式事务步骤(以转账为例): 第一步:业务的层的哪些方法需要事务
package com.cc.service; public interface IUserInfoService { /* * from:转出的账户 to:转入的账户 money:转的金额 * */ public void zz(int from, int to, int money) throws Exception; }第二步:在spring-datasource.xml中配置事务管理器 (注意:不同的orm框架 事务管理的方式不同)
<!--spring针对MyBaits的事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>第三步:在spring-datasource.xml中定义切面(注:切面=切点+通知)
<!-- 1、通知(增强+连接点) --> <tx:advice id="txAdice" transaction-manager="transactionManager"> <tx:attributes> <!-- 所有以zz结束的方法 都会被匹配 --> <tx:method name="*zz"/> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <!-- 2、植入 --> <aop:config> <!-- 切点 --> <aop:pointcut id="txPoint" expression="execution(* com.cc.service.impl.UserInfoServiceImpl2.*(..) )" /> <!-- 切面(advisor/aspect)=切点和通知 --> <aop:advisor advice-ref="txAdice" pointcut-ref="txPoint"/> </aop:config>要注意的几个属性: 1.read-only:只读事务 在事务内不能修改数据 2.isolation=“DEFAULT”:指定事务隔离级别 3. rollback-for="" :指定方法产生哪种异常才进行事务的回滚 4. no-rollback-for="" :指定方法产生哪种异常不进行事务的回滚 5. timeout:事务的过期时间 6. propagation=“REQUIRED” 事务传播特性
第四步:在xml配置根据切点+增强 ,自动生成业务方法的代理对象
package com.cc.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionTemplate; import com.cc.mapper.UserInfoMapper; import com.cc.model.UserInfo; import com.cc.service.IUserInfoService; //业务层 @Component public class UserInfoServiceImpl2 implements IUserInfoService { @Autowired private UserInfoMapper userInfoMapper; @Autowired private TransactionTemplate transactionTemplate; // @Autowired // public UserInfoServiceImpl1(PlatformTransactionManager transactionManager) { // this.transactionTemplate = new TransactionTemplate(transactionManager); // } /** * 转账业务:旺财(from)转账给来福(to),转money钱 * * 旺财(from) 更新操作 减money 来福 (to) 更新操作 加money money =200 * * * zz(1,2,300) */ @Override public void zz(int from, int to, int money) throws Exception { // 转账的操作 zzOptional(from, to, money); } private void zzOptional(int from, int to, int money) throws Exception { // 一,==============旺财的钱减少300============== // 1.1查询旺财有多少钱 UserInfo wc = userInfoMapper.selectByPrimaryKey(from); System.out.println(wc); // 1.2扣旺财有300 wc.setMoney(wc.getMoney() - money); int result = userInfoMapper.updateByPrimaryKey(wc); // ==============二,来福的钱增加300============== // 1.1查询旺财有多少钱 UserInfo lf = userInfoMapper.selectByPrimaryKey(to); System.out.println(lf); // 1.2扣旺财有300 lf.setMoney(lf.getMoney() + money); int result2 = userInfoMapper.updateByPrimaryKey(lf); // ==============最后的结果============== if (result > 0 && result2 > 0) { System.out.println("转账成功!!"); } else { // int a = 10/0;//产生一个异常 throw new Exception("转账失败");// 产生一个异常 } } }第五步:编写单元测试方法
package com.cc.proxy; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.cc.mapper.UserInfoMapper; import com.cc.service.IUserInfoService; import com.cc.service.impl.UserInfoServiceImpl1; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring-datasource.xml") public class SpringTrasactionTest { // 声明式事务的业务层类 @Autowired @Qualifier("userInfoServiceImpl2") private IUserInfoService iUserInfoService; @Test public void whenZz2Success() { try { iUserInfoService.zz(1, 2, 100); } catch (Exception e) { System.out.println("转账失败,回滚"); System.out.println(e.getMessage()); } } }