背景:
有个业务是这样的,先执行导入操作,导入提交后再异步执行其他业务,数据依赖导入数据。
1. 主方法
@Transactional(rollbackFor = Exception.class)
public void testA() {
long begin = System.currentTimeMillis();
BrandInfo brandInfo = new BrandInfo();
brandInfo.setBrandCode("brandCode1");
brandInfo.setBrandName("brandName1");
this.save(brandInfo);
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
productInfoService.testA();
}
}
);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("主方法执行时间:"+(end - begin));
}
2. 异步执行方法,需要不同的service
@Async
@Transactional(rollbackFor = Exception.class)
public void testA() {
long begin = System.currentTimeMillis();
try {
LambdaQueryWrapper<BrandInfo> brandInfoQueryWrapper = Wrappers.lambdaQuery();
List<BrandInfo> brandInfoList = brandInfoMapper.selectList(brandInfoQueryWrapper);
System.out.println("查询后数据:" + JSONUtil.toJsonStr(brandInfoList));
for (int i = 0; i < 10; i++) {
ProductInfo productInfo = new ProductInfo();
productInfo.setProductCode("productCode" + i);
productInfo.setProductName("productName" + i);
// if (i == 5) {
// throw new RuntimeException("异步执行异常");
// }
this.save(productInfo);
}
Thread.sleep(5000);
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
BrandInfo brandInfo = new BrandInfo();
brandInfo.setBrandCode("B1");
brandInfo.setBrandName("B2");
brandInfoService.testInsert(brandInfo);
//e.printStackTrace();
}
System.out.println("异步执行");
long end = System.currentTimeMillis();
System.out.println("异步方法执行时间:" + (end - begin));
}
3. 实体类
@Data
public class BrandInfo extends BaseEntity{
private String brandCode;
private String brandName;
}
@Data
public class ProductInfo extends BaseEntity{
private String productCode;
private String productName;
}
结语:
1. @Transactional和@Async的不生效的问题,同一个类 @Async不生效,导致子方法回滚,主方法也会回滚。如果是不同service @Async生效,不会导致主方法回滚。
2.同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用。原理:spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。