REQUIRES_NEW:
当前方法必须启动新事务,并在它自己的事务内运行,如果有事务在运行,则把当前事务挂起
-
测试类:
场景:一个人(id为aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa)的钱包有100元,它想买两类书,第一类id为a2f39533-659f-42ca-af91-c688a83f6e49,数量为1本,单价为10元,该书库存为10本;第二类id为4c37672a-653c-4cc8-9ab5-ee0c614c7425,数量为10,单价为10元,该书库存为10本;package com.jd.test; import java.util.*; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.jd.car.ICarService; import com.jd.car.imp.CarService; public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("application.xml"); ICarService carService = application.getBean(CarService.class); String userId = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"; Map<String,Integer> commodities = new HashMap<String,Integer>(); commodities.put("a2f39533-659f-42ca-af91-c688a83f6e49",1); commodities.put("4c37672a-653c-4cc8-9ab5-ee0c614c7425",10); carService.batch(userId, commodities); application.close(); } }
-
CarService类
package com.jd.car.imp; import java.util.*; import java.util.Map.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.jd.car.ICarService; import com.jd.coupon.ICouponService; @Service public class CarService implements ICarService { @Autowired private ICouponService couponService; //购物车购买 @Override @Transactional public boolean batch(String userId,Map<String,Integer> commodities) { Set<Entry<String, Integer>> set = commodities.entrySet(); for (Entry<String, Integer> commodity : set) { String bookId = commodity.getKey(); int count = commodity.getValue(); System.out.println(bookId+","+count); couponService.insert(userId,bookId, count); } return true; } }
-
CouponService类
package com.jd.coupon.imp; import java.util.*; import java.util.Map.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.jd.book.IBookDao; import com.jd.coupon.ICouponDao; import com.jd.coupon.ICouponService; import com.jd.money.IMoneyDao; import com.jd.vo.Coupon; @Service public class CouponService implements ICouponService { @Autowired private IBookDao bookDao; @Autowired private IMoneyDao moneyDao; @Autowired private ICouponDao couponDao; //立即购买 @Override @Transactional(propagation=Propagation.REQUIRES_NEW) public boolean insert(String userId,String bookId, int count){ if(bookDao.enough(bookId, count)) {//书籍足够 //书籍表库存递减 bookDao.update(bookId, count); } double price = bookDao.getPrice(bookId); double total = price*count; if(moneyDao.enough(userId, total)) {//余额足够 //订单表添加数据 Coupon coupon = new Coupon(); coupon.setId(UUID.randomUUID().toString()); coupon.setUserId(userId); coupon.setBookId(bookId); coupon.setTotal(total); couponDao.insert(coupon); //钱包表递减 moneyDao.update(userId, total); } return true; } }
分析:
修饰insert方法的@Transactional注解中添加了“propagation=Propagation.REQUIRES_NEW”属性,则每次执行该方法时都会启动新事务,所以结算第一类书籍时钱够库存也够则购买成功并提交当次事务,但结算第二类书籍时由于钱包钱不够导致支付失败,致使此次事务回滚。