java事务服务_Java事务失效

问题复现,用伪代码复现问题!

事务配置文件

controller层代码

/** * excel批量导入信息 */

@RequestMapping(path="/pre/pretemplate/importExcel/{templateType}")

public Map importCrm(@PathVariable String templateType, MultipartFile[] file, HttpServletRequest req) throws Exception{

User user = getSessionUser(req);

Map data = null;

//0 老师 1 学生

if("0".equals(templateType)) {

data = service.updateExcel(file[0], req,templateType);

if ((boolean) data.get("success")) {

service.writeSystemLog("批量导入老师数据成功");

} else {

service.writeSystemLog("批量导入老师数据失败");

}

}

if("1".equals(templateType)) {

data = service.updateExcel(file[0], req,templateType);

if ((boolean) data.get("success")) {

service.writeSystemLog("批量导入学生数据成功");

} else {

service.writeSystemLog("批量导入学生数据失败");

}

}

return data;

}

service层代码

public Map updateExcel(MultipartFile file, HttpServletRequest req, String templateType) throws Exception {

.........//权限与数据的处理

data = importService.importLevelExcel(file, templateType);

if (!(boolean) data.get("success")) {

return data;

}

// 将数据插入数据库

data.put("msg", "信息导入成功!");

return data;

}

public Map importLevelExcel(MultipartFile file, String templateType) throws Exception {

HSSFWorkbook hwb;

Map map = new LinkedHashMap<>();

hwb = new HSSFWorkbook(file.getInputStream());

HSSFSheet sheet = hwb.getSheetAt(0);

try{

........

String target = getCellValue(row.getCell(2));

String method = getCellValue(row.getCell(3));

//检验是否包含特殊字符

checkForString(method);

}catch (Exception e) {

map.put("success", false);

map.put("msg", "数据类型异常,请检查!");

return map;

}

}

业务需求:需要在用Excel模板导入信息时进行判断,Windows系统下新建文件夹不支持的符号不能导入!

因为导入模板信息较多,所以我写了一个公共方法,在导入时进行调用进行校验

public void checkForString(String str) throws Exception {

String regEx = "[\\/:*?\"<>|]";

Pattern p = Pattern.compile(regEx);

Matcher m = p.matcher(str);

bolean b = m.find();

if (b) {

throw new BusinessException("数据中不能包含:“\\\\/:*?\"<>|”中任何字符!");

}

}

本以为这样就结束了,没想到经过测试后发现,消息提示什么的都没问题,但是即便是在模板信息中含有特殊字符的情况下,还是可以成功保存几条数据,也就是说事务有问题,顺着思路去配置文件一看,只有service里面的第一级方法有事务,所以在配置文件中添加了导入方法的事务。

本想着加完就可以愉快的结束,没想到问题还是没有解决,于是我上百度上遨游了一圈,发现当前加事务的方法中异常被try-catch捕获了,导致异常处理器不能捕捉到异常,事务出现问题。

但是方法中不仅要返回弹框提示信息,还有返回日志信息,保存用户操作日志,这该怎么办?

经过思考我决定将异常放在service最顶级方法处理,根据异常类进行信息回写,service代码改成

public Map updateExcel(MultipartFile file, HttpServletRequest req, String templateType) throws Exception {

.........//权限与数据的处理

try{

data = importService.importLevelExcel(file, templateType);

} catch (BusinessException bus) {

data.put("success", false);

data.put("msg", "导入模板中不能包含:“\\/:*?\"<>|”中任何字符!");

return data;

} catch (Exception e) {

data.put("success", false);

data.put("msg", "数据类型异常,请检查!");

return data;

}

return data;

}

public Map importLevelExcel(MultipartFile file, String templateType) throws Exception {

HSSFWorkbook hwb;

Map map = new LinkedHashMap<>();

hwb = new HSSFWorkbook(file.getInputStream());

HSSFSheet sheet = hwb.getSheetAt(0);

........

String target = getCellValue(row.getCell(2));

String method = getCellValue(row.getCell(3));

//检验是否包含特殊字符

checkForString(method);

}

到此为止,我觉得我已经大功告成,但是经过测试,还有问题,我就有点纳闷了!

经过查询才知道,原来同类中子方法的事务是无效的,什么嵌套还有传播通通无效,但是我想想自己的父级方法不是有事务吗?为什么还是失效,最后才明白,原来是我在父级方法中try-catch了,导致整体都没有事务了

解决办法有两种:

1.将子方法放在其他service下

2.调用子方法前,重新获取bean对象

于是我在service中重新获取bean对象,就OK了

总结:

1.spring事务管理中,如果方法参与了事务,就不能在方法中进行try-catch,否则事务控制器无法捕获事务,事务失效

2.同类方法中,如果父类参与了事务管理,那么即便子类重新添加了事务,哪怕是不同传播等级的事务,还是无效,spring默认集成父类的事务。如果想子类单独处理事务,有两种解决方案

​ A:将子方法放在其他service下

​ B:调用子方法前,重新获取bean对象

如若有误,欢迎指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值