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

事务配置文件

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- TODO 事务隔离级别可以尝试 NESTED -->
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" read-only="true" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>

controller层代码

/** * excel批量导入信息 */
@RequestMapping(path="/pre/pretemplate/importExcel/{templateType}")
public Map<String, Object> importCrm(@PathVariable String templateType, MultipartFile[] file, HttpServletRequest req) throws Exception{
User user = getSessionUser(req);
Map<String, Object> 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<String, Object> 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<String, Object> importLevelExcel(MultipartFile file, String templateType) throws Exception {
HSSFWorkbook hwb;
Map<String, Object> 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里面的第一级方法有事务,所以在配置文件中添加了导入方法的事务。

<tx:method name="importLevelExcel" propagation="REQUIRES_NEW" rollback-for="Exception"/>

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

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

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

public Map<String, Object> 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<String, Object> importLevelExcel(MultipartFile file, String templateType) throws Exception {
HSSFWorkbook hwb;
Map<String, Object> 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对象

如若有误,欢迎指正!

Java事务失效的更多相关文章

  1. java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现

    注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...

  2. 转!!java事务的处理

    java的事务处理,如果对数据库进行多次操作,每一次的执行或步骤都是一个事务.如果数据库操作在某一步没有执行或出现异常而导致事务失败,这样有的事务被执行有的就没有被执行,从而就有了事务的回滚,取消先前 ...

  3. 深入Java事务的原理与应用

    一.什么是JAVA事务    通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 ( ...

  4. java事务管理

    一.什么是Java事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性(isol ...

  5. java事务的处理

    java的事务处理,如果对数据库进行多次操作,每一次的执行或步骤都是一个事务. 如果数据库操作在某一步没有执行或出现异常而导致事务失败,这样有的事务被执行有的就没有被执行,从而就有了事务的回滚,取消先 ...

  6. spring声明式事务 同一类内方法调用事务失效

    只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务 [问题] Spring的声明式事务,我想就不用多介绍了吧,一句话“自从用了Spring ...

  7. SpringMvc配置 导致实事务失效

    SpringMVC回归MVC本质,简简单单的Restful式函数,没有任何基类之后,应该是传统Request-Response框架中最好用的了. Tips 1.事务失效的惨案 Spring MVC最打 ...

  8. spring事务失效情况分析

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt113 <!--[if !supportLists]-->一.&l ...

  9. spring声明式事务 同一类内方法调用事务失效(转)

    原文 https://blog.csdn.net/jiesa/article/details/53438342 [问题] Spring的声明式事务,我想就不用多介绍了吧,一句话“自从用了Spring ...

随机推荐

  1. 关于6410板文件的dm9000的平台设备地址

    转自csdn #define CONFIG_DM9000_BASE 0x20000300#define DM9000_IO                      0x20000000#define ...

  2. Export与import命令

    模块功能主要由两个命令构成:export和import. export命令用于用户自定义模块,规定对外接口: import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函 ...

  3. 学习C#泛型

    C#泛型详解 C#菜鸟教程 C#中泛型的使用

  4. Android ListView显示底部的分割线

    有些时候,我们会提出这样的需求,希望ListView显示底部(顶部)的分割线,这样做,会使得UI效果更加精致,如下图所示: 如果搜索资料,大家会搜到一堆相关的方法,最多的莫过于设置listview的f ...

  5. element表格多选实现单选

    9.element多选表格实现单选 userChoose(selection, row) { console.log(selection,'selection') console.log(row,'r ...

  6. web项目的文件上传和 下载

    文件上传和下载在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用Java开发的文件上传组件,本文以commons-fileupload组件为例,为jsp应用添加文件 ...

  7. 开源CMS比较

    PHP-CMS的发展方向:简单,易用,美观  http://www.php-cms.cn/ 看点1,服务器一键安装,鼠标点点就搞定:输入数据库参数,在服务器上点一个按钮就完成全部的安装.简单配置一下网 ...

  8. KMPnext数组运用、最小循环节问题

    http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html http://www.cnblogs.com/wuyiqi/archive/ ...

  9. 浅谈Transformer 及Attention网络

    1 Transformer 模型结构处理自然语言序列的模型有 rnn, cnn(textcnn),但是现在介绍一种新的模型,transformer.与RNN不同的是,Transformer直接把一句话 ...

  10. js 键盘事件keyCode 总结

    开发中经常页面中的某些按钮或元素需要绑定到键盘的输入事件 keydown.keyup 事件 keydown 键盘按下触发事件 $("#btn").keydown(function( ...