spring注解事务使用总结

spring注解事务使用总结

        在使用spring的注解事务的时候,需要考虑到事务的传播行为、遇到什么类型的异常时,事务才起作用、事务方法之间的嵌套调用时,怎么样才生效等等诸多问题。网上搜到很多的主要还是一堆理论文字描述,我这里给出亲测的代码,是借助公司真实的系统来做测试。

 

系统之间调用图如下:

 

事务和异步处理都在server模块里面。 

 

 接口如下:

/**
 * 测试事务行为接口
 * 
 * @author plg
 *
 */
public interface TestService {

    public void methodA();

    public void methodB();

    public void methodC();
    
    .
    .
    .
}

 

 使用两个表:

CREATE TABLE `mall_order_statistics` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `shop_id` bigint(20) NOT NULL,
  `order_num` bigint(20) NOT NULL,
  `order_amount` bigint(20) NOT NULL,
  `avg_order_amount` bigint(20) NOT NULL,
  `pay_type` int(11) NOT NULL,
  `order_type` int(11) NOT NULL',
  `order_date` date NOT NULL,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_shop_id` (`shop_id`)
) ENGINE=InnoDB


CREATE TABLE `mall_goods_ranking` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `shop_id` bigint(20) NOT NULL,
  `order_date` date NOT NULL,
  `mall_goods_id` bigint(20) NOT NULL,
  `goods_name` varchar(20) NOT NULL,
  `sales_volume` bigint(20) NOT NULL,
  `sales_amount` bigint(20) NOT NULL,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_shop_id` (`shop_id`)
) ENGINE=InnoDB

 

1.事务与异常类型

这里用的是注解式事务@Transactional。

1.1 正常的处理

        先来一个正常的处理,事先已把数据库表清空,代码调用如下:

web端代码如下:
try {
    testService.methodA();
} catch (Exception e) {
	logger.error("========================= " + e);
}

server端代码如下:
@Transactional
@Override
public void methodA() {
	MallGoodsRanking mallGoodsRanking = new MallGoodsRanking();
	mallGoodsRanking.setShopId(1L);
	mallGoodsRanking.setOrderDate(new Date());
	mallGoodsRanking.setMallGoodsId(1L);
	mallGoodsRanking.setGoodsName("测试");
	mallGoodsRanking.setSalesVolume(1L);
	mallGoodsRanking.setSalesAmount(1L);
	mallGoodsRanking.setCreateTime(new Date());
	mallGoodsRankingMapper.insert(mallGoodsRanking);

	MallOrderStatistics mallOrderStatistics = new MallOrderStatistics();
	mallOrderStatistics.setShopId(1L);
	mallOrderStatistics.setOrderNum(1L);
	mallOrderStatistics.setAvgOrderAmount(1L);
	mallOrderStatistics.setOrderAmount(1L);
	mallOrderStatistics.setPayType(1);
	mallOrderStatistics.setOrderType(1);
	mallOrderStatistics.setOrderDate(new Date());
	mallOrderStatistics.setCreateTime(new Date());
	mallOrderStatisticsMapper.insert(mallOrderStatistics);
}
         执行结果:

 

  1.2异常处理-不插入必填字段,抛出RuntimeException  

1.3异常处理-不插入必填字段,抛出Exception

@Transactional
@Override
public void methodA() throws Exception {
	try {
		MallGoodsRanking mallGoodsRanking = new MallGoodsRanking();
		mallGoodsRanking.setShopId(1L);
		mallGoodsRanking.setOrderDate(new Date());
		mallGoodsRanking.setMallGoodsId(1L);
		mallGoodsRanking.setGoodsName("测试");
		mallGoodsRanking.setSalesVolume(1L);
		mallGoodsRanking.setSalesAmount(1L);
		mallGoodsRanking.setCreateTime(new Date());
		mallGoodsRankingMapper.insert(mallGoodsRanking);

		MallOrderStatistics mallOrderStatistics = new MallOrderStatistics();
		// mallOrderStatistics.setShopId(1L);必填字段
		mallOrderStatistics.setOrderNum(1L);
		mallOrderStatistics.setAvgOrderAmount(1L);
		mallOrderStatistics.setOrderAmount(1L);
		mallOrderStatistics.setPayType(1);
		mallOrderStatistics.setOrderType(1);
		mallOrderStatistics.setOrderDate(new Date());
		mallOrderStatistics.setCreateTime(new Date());
		mallOrderStatisticsMapper.insert(mallOrderStatistics);
	} catch (Exception e) {
                logger.error(" ================== " + e);
                throw new Exception("异常");
	}
}
捕捉异常后,然后 throw new Exception。执行后,抛出异常: 1.3异常处理-不插入必填字段,抛出Exception
java.lang.Exception: 异常
	at yunnex.saofu.mall.service.impl.TestServiceImpl.methodA(TestServiceImpl.java:55)
	at yunnex.saofu.mall.service.impl.TestServiceImpl$$FastClassBySpringCGLIB$$8fcf06b.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
  执行结果:
 

 看到了吗,第一条SQL还是插入成功了,第二条语句插入出错,抛出Exception异常,但是事务并没有回滚。 接下来测试一下@Transactional(rollbackFor=Exception.class)这种情况。  

1.4异常处理-不插入必填字段,抛出Exception,@Transactional指定异常类型

1.4异常处理-不插入必填字段,抛出Exception,@Transactional指定异常类型              由于篇幅问题,这里补贴代码了,和1.3不同的就是事务注解改成:@Transactional(rollbackFor = Exception.class),运行之后,事务生效:

 

 数据库表没有插入数据。         对于service方法中使用注解事务,要么service中的方法中不做异常捕获,要么捕捉异常后throw new RuntimeException(),这样出现异常时,都会使事务回滚。如果需要捕捉特定类型的异常来回滚事务,则需要用@Transactional(rollbackFor=特定类型异常.class)来指定。  =================================================================================================================================   2.事务方法嵌套使用

猜你喜欢

转载自plg17.iteye.com/blog/2358924