spring事务失效解决方法并进行事务的部分回滚

内容:

1.spring事务失效场景。

2.解决方案.

3.Spring事务回滚到指定片段。

场景描述:

当我们从12306点击最后一步付款操作,后台有两步操作。1.将乘客用户信息插入到订单表。2.向用户手机发送短信提示。

因为发送短信的方法需要掉外部网关,在这一步通常会发生发送失败。我希望当发送短信这个方法不影响我整体业务,即即使不发送短信车票订单同样向数据库中插入。

问题1:spring事务失效

在上一篇例子中的代码进行点修改。拿出关键代码


@Service
@EnableTransactionManagement
public class EmpService {
	@Autowired
	EmpDao empDao;
	public Emp selectById(String id){
		return empDao.selectById(id);
	}

	/**
	 * 订票
	 */
	@Transactional()
	public void bookTicket(){
		empDao.addEmp();//模拟插入操作,数据库中插入一条记录
		sendMsg();
	}
	/**
	 * 发送短信提示
	 */
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void sendMsg(){	
		empDao.addEmp1();//模拟发送短信操作,数据库中插入一条记录
	}
}


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:cn/rjx/spring/aopandtxdisable/bean.xml"}) //加载配置文件   
@Component
@ComponentScan(basePackages="cn.rjx.spring.aopandtxdisable")
public class EmpTest {
	Logger logger=LoggerFactory.getLogger(EmpService.class);
	@Autowired
	EmpService service;

	@Test
	public void test02(){
		logger.info("--------------------bookTicket----------------------------------------------");
		service.bookTicket();
	}

}

日志信息可以看到事务只注册一次:

spring事务失效解决方法并进行事务的部分回滚_第1张图片

动态代理解释原因:执行bookTicket()方法是由代理类通过invoke()执行委托类的方法,并在该方法前后做了增强。而bookTicket()中的sendMsg()方法调用者为this即当前类实例,也就是委托类本身。而sendMsg()方法并没有做增强操作。可以查看我写的动态代理的那一节实现方式。


spring解决方法:

@EnableAspectJAutoProxy(exposeProxy=true)

AopContext.currentProxy()


@Service
@EnableTransactionManagement
/**
    
    
 */
@EnableAspectJAutoProxy(exposeProxy=true)
public class EmpService {
	@Autowired
	EmpDao empDao;
	public Emp selectById(String id){
		return empDao.selectById(id);
	}
	@Transactional()
	public void accountChange() {
		empDao.addSalary("1");
		int a=10/0;
		empDao.updateSalary("2");
	}
	/**
	 * 订票
	 */
	@Transactional()
	public void bookTicket(){
		empDao.addEmp();
		//AopContext.currentProxy()获取当前aop的代理
		EmpService serviceProxy=(EmpService)AopContext.currentProxy();		
		serviceProxy.sendMsg();
	}
	/**
	 * 发送短信提示
	 */
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void sendMsg(){
		empDao.addEmp1();

	}
}

日志打印:

spring事务失效解决方法并进行事务的部分回滚_第2张图片



回滚指定段:

网上贴子都是通过rollbackFor捕获异常来处理的,感觉挺麻烦效果也不怎么好用。官网文档中有一段写关于回滚的,也推荐我们这么做!

spring事务失效解决方法并进行事务的部分回滚_第3张图片

意思用这用方法能将您的代码与Spring Framework处理架构紧密耦合。


	/**
	 * 订票
	 */
	@Transactional()
	public void bookTicket(){
		empDao.addEmp();
		//AopContext.currentProxy()获取当前aop的代理
		EmpService serviceProxy=(EmpService)AopContext.currentProxy();		
		serviceProxy.sendMsg();
	}
	/**
	 * 发送短信提示
	 */
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void sendMsg(){
		try {
			empDao.addEmp1();
			throw new RuntimeException();
		} catch (Exception e) {
			/**
			 * 由事务管理切面获取当前事务的状态,(查看是否完成,是否回滚)仅仅回滚当前状态
			 */
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
	}

日志打印:只回滚了发短信那个事务。订票事务没回滚。数据库也只插入一条数据。

spring事务失效解决方法并进行事务的部分回滚_第4张图片




参考:http://blog.csdn.net/wxwzy738/article/details/27566645

你可能感兴趣的:(spring)