使用@Transactional需要注意的问题:
1.只对 Error或者RuntimeException 异常生效,如果要其他事务要加上(rollbackFor = Exception.class)
2.注解只能应用到 public 可见度的方法上。 如果应用在protected、private或者 package可见度的方法上,也不会报错,不过事务设置不会起作用。
3.不能用try catch
4.数据库引擎要支持事务,如果是mysql,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的。
如果一定要用trycatch 可以手动在catch中加回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
下面是自定义异常回滚示例
@APIMethod(name = "商品企划添加", category = SystemConstants.SoaApiCategory.BaseDataPlant, apiUsers = ("ALL"), version = "1.0", desc = "商品企划添加", authors = "xjh")
@RequestMapping(value = "/addPlant", method = RequestMethod.POST)
@Transactional(rollbackFor = Exception.class)
public Payload otbPlantAdd(@RequestBody OtbPlantDtos otbPlantDtos)throws Exception{
//1.校验参数
Payload resp = new Payload();
resp.setCode("-1");
//保存otb列表的
//保存商品企划列表的
List<OtbPlantDto> otbPlantDtoList = otbPlantDtos.getOtbPlantDtos();
if(otbPlantDtoList.size()>0){
OtbBase otbBase = new OtbBase();
BeanUtils.copyProperties(otbPlantDtoList.get(0),otbBase);
otbBase.setCreatedTime(new Date());
otbBase.setUpdatedTime(new Date());
otbBase.setDr(0);
otbBase.setStatus("-1");
if(otbPlantDtos.getDimensionVersion() == null){
resp.setMsg("传入的dimensionVersion为空");
throw new Exception ("传入的dimensionVersion为空");
}
otbBase.setDimonsionVersion(otbPlantDtos.getDimensionVersion());
otbBaseMapper.insert(otbBase);
BigDecimal saleTotalMoney = BigDecimal.ZERO;
for(OtbPlantDto otbPlantDto:otbPlantDtoList){
if(StringUtils.isBlank(otbPlantDto.getSubjects())){
resp.setMsg("科目为空");
throw new Exception ("科目为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getValues())){
resp.setMsg("科目对应的值为空");
throw new Exception ("科目对应的值为空"+ JSONObject.toJSONString(otbPlantDto));
}
//保存otb列表的
if(StringUtils.isBlank(otbPlantDto.getBrandId())){
resp.setMsg("品牌id为空");
throw new Exception ("科目对应的值为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getBrandName())){
resp.setMsg("品牌名称为空" );
throw new Exception ("品牌名称为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getYear())){
resp.setMsg("年份为空" + JSONObject.toJSONString(otbPlantDto));
throw new Exception ("年份为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getDelivery())){
resp.setMsg("期货为空");
throw new Exception ("期货为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getOtbVersion())){
resp.setMsg("Otb版本为空");
throw new Exception ("Otb版本为空" + JSONObject.toJSONString(otbPlantDto));
}
if(StringUtils.isBlank(otbPlantDto.getCreatedId())){
resp.setMsg("新建人为空");
throw new Exception ("新建人为空" + JSONObject.toJSONString(otbPlantDto));
}
String[] subjectArray = otbPlantDto.getSubjects().split(",");
String[] valueArray = otbPlantDto.getValues().split(",");
if(subjectArray.length != valueArray.length){
resp.setMsg("科目(subjects)和科目对应的值(values)数量不一样多");
throw new Exception ("科目(subjects)和科目对应的值(values)数量不一样多" + JSONObject.toJSONString(otbPlantDto));
}
OtbBaseDataPlant otbBaseDataPlant = new OtbBaseDataPlant();
otbBaseDataPlant.setCreatedTime(new Date());
otbBaseDataPlant.setUpdatedId(otbPlantDto.getCreatedId());
otbBaseDataPlant.setUpdatedTime(new Date());
otbBaseDataPlant.setBaseId(otbBase.getId());
otbBaseDataPlant.setCreatedId(otbPlantDto.getCreatedId());
otbBaseDataPlant.setAreaDetailed(otbPlantDto.getAreaDetailed());
Map<String, BigDecimal > otbBaseDataPlantMap = BeanMapConvert.convertBean(otbBaseDataPlant);
for(int i = 0;i < subjectArray.length;i++ ){
if(!valueArray[i].equals("null")){
otbBaseDataPlantMap.put(OtbSubjectNewEnum.getCodeByName(subjectArray[i]),new BigDecimal(valueArray[i]));
if(subjectArray[i].equals(OtbSubjectNewEnum.TOTALSALESTARGET.getSubject())){
saleTotalMoney = saleTotalMoney.add(new BigDecimal(valueArray[i]));
}
}
}
otbBaseDataPlant = (OtbBaseDataPlant) BeanMapConvert.convertMap(OtbBaseDataPlant.class,otbBaseDataPlantMap);
otbBaseDataPlantMapper.insert(otbBaseDataPlant);
}
//金额修改
otbBase.setSaleTotalMoney(saleTotalMoney);
otbBaseMapper.update(otbBase);
}else{
resp.setMsg("添加数据为空");
return resp;
}