文章参考了此博客: https://blog.csdn.net/qq_40594137/article/details/82772545

写这篇文章之前先说明一下:

1. Controller中添加事务管理,是可行的,但是强烈不推荐,因为不符合实际开发场景,还会导致一系列问题

2. 事务请在Service处理,所有的业务逻辑请写在 Service, Service中异常请抛出,慎用 try...catch捕获异常

写这边文章的背景:

公司有个老的项目,springMVC + spring + mybatis,事务是在Service层处理的,但是之前的开发人员把很多业务逻辑写在了 Controller,出现了操作失败仍然将数据写入数据库的bug.....,于是开始研究在 Controller中添加事务管理

Controller中添加事务管理步骤:

1. spring.xml中事务配置不变

2. 在spring-mvc.xml中定义事务配置:

A: 命名空间中 加入约束 不加项目启动会报异常:
             xmlns:tx="http://www.springframework.org/schema/tx"
             http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

         B:  定义事务注解解析  <tx:annotation-driven transaction-manager="transactionManager" />

3. 在需要控制事务的Controller 类或者方法上使用 @Transactional(rollbackFor = {Exception.class}) ,当出现异常回滚

需要注意的是:  Controller层只支持 @Transactional 注解式事务!

关于为什么要在spring-mvc.xml中添加 <tx:annotation-driven transaction-manager="transactionManager" />  的说明:

错误的方式----通过修改spring.xml中的配置来实现在controller中控制事务会发现事务无效,如下:

<aop:config>  
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* net.*.controller.*.*(..))"/></aop:config> 

原因如下:  spring容器和spring-mvc是父子容器。在服务器启动时,会先加载web.xml配置文件 ==> 再加载spring配置文件 ==> 再回到web.xml【加载监听器;加载过滤器;加载前端控制器】==>再加载springMVC配置文件,在Spring配置文件中,我们扫描注册的是service实现类,就算扫描注册了controller 也会在后面加载SpringMVC配置文件[扫描注册controller]覆盖掉,所以想要在controller中实现事务管理,仅在spring配置文件配置<tx:annotation-driven>或<aop:config>是没有效果的,必须将事务配置定义在Spring MVC的应用上下文(spring-mvc.xml)中。在spring-framework-reference.pdf文档中说明了: <tx:annoation-driven/>只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解

关于 @Transactional 注解的一些说明:

有篇博客写的很好,我就直接链接了 https://www.jianshu.com/p/befc2d73e487

关于@Transaction 事务不起作用的总结:

@Transaction不起作用的情况:1.静态(static )方法

2.(private)私有化方法

3.当本类的使用@Transactional的方法被本类的其它没有开启事务的方法调用时,不会开启事务。

使用@Transactional的方法被其它类调用时,按照正常的事务传播行为规则开启事务

4.未开启注解解析: 配置文件必须加<tx:annotation-driven />,否则不解析@Transactional

5.异常被try{}catch(){}捕捉到了,有异常就不会回滚。

6. 数据库引擎要支持事务: 如果是mysql,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的

项目中问题的最终处理:

由于 Controller 层中异常不能直接抛到用户,对异常进行了try{}catch(){},导致事务回滚失效,无法通过在 Controller 层添加事务管理来实现事务功能,

所以只能有用以下方式来处理:

1. 将业务逻辑代码移到 service 来处理 : 推荐方法

2. 如果业务逻辑复杂,在维护的时候无法保证逻辑正确的情况下,只有手动编写事务代码来实现回滚了,具体代码如下:(不推荐)

//在每个controller中注入transactionManager
@Resource
private PlatformTransactionManager transactionManager; @PostMapping(value = "setCode")
@ResponseBody
public void setCode(Invoice invoice, InvoiceAddress invoiceAddress,String token,String orderIDs,
Integer pid,HttpServletResponse response){ DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition); try {
invoiceService.insert(token,pid,invoice);
int iID= invoice.getId();
String substring = orderIDs.substring(0, orderIDs.length()-1);
String[] split = substring.split(",");
for (String string2 : split) {
bOrderService.updateIStatus("1",string2);
}
invoiceOrderService.insert(iID,substring);
if(Integer.parseInt(invoice.getiType())==1){
invoiceAddressService.insert(iID,invoiceAddress);
} System.out.println("======制造一个运行时异常aa======");
System.out.println("运行时异常:"+100/0); //没有异常便手动提交事务
transactionManager.commit(status);
printJson(response,result(200,"ok"));
}catch (Exception e){
//有异常便回滚事务
transactionManager.rollback(status);
e.printStackTrace();
printJson(response,result(500,"false"));
} }

 

  

在Controller中添加事务管理的更多相关文章

  1. Spring中的事务管理

    事务简介: 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性 事务就是一系列的动作,它们被当作一个单独的工作单元.这些动作要么全部完成,要么全部不起作用 事务的四个关键属性( ...

  2. ASP.NET MVC 学习4、Controller中添加SearchIndex页面,实现简单的查询功能

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-method ...

  3. Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

  4. 代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性

    做人事档案的系统考虑到数据的安全性与一致性,毕竟是要对外上线.真正投入使用的项目,数据库的可靠性与安全性上我们开发人员要考虑的就很多了,记得做机房收费系统时注册新卡是自己为了简单,写成了一个存储过程( ...

  5. Spring框架学习笔记(10)——Spring中的事务管理

    什么是事务 举例:A给B转500,两个动作,A的账户少500,B的账户多500 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 一.注解添加事务管理方 ...

  6. spring将service添加事务管理,在applicationContext.xml文件中的设置

    在applicationContext.xml文件中的设置为: <beans> <bean id="sessionFactory" class="org ...

  7. Spring Boot中的事务管理

    原文  http://blog.didispace.com/springboottransactional/ 什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合 ...

  8. 使用sftp操作文件并添加事务管理

    本文主要针对文件操作的事务管理,即写文件和删除文件并且能保证事务的一致性,可与数据库联合使用,比如需要在服务器存文件,相应的记录存放在数据库,那么数据库的记录和服务器的文件数一定是要一一对应的,该部分 ...

  9. Spring Boot 中的事务管理

    希望能在发生异常的时候被回退,这时候就可以使用事务让它实现回退,做法非常简单,我们只需要在test函数上添加@Transactional注解即可. 使用@Transactional注解来声明一个函数需 ...

随机推荐

  1. MySQL悲观

    //0.开始事务 begin;/begin work;/start transaction; (三者选一就可以) //1.查询出商品信息 for update; //2.根据商品信息生成订单 inse ...

  2. label vc

    #pragma once #include <QWidget> #include <QPaintEvent> #include <QPainter> #includ ...

  3. Failed to open .vcf.gz: could not load index

    这类报错在我使用bcftools index file.vcf.gz进行index出现的. 解决办法是换用tabix进行index,命令为tabix -p vcf file.vcf.gz. 用tabi ...

  4. bladex开发自己的服务不推送服务器的方法

    一:问题 使用代码生成器 生成的代码,运行后,需要推送至服务器才可以进行调试,每次推送,启动服务至少半个小时以上,相当浪费时间,如何可以让开发的服务不推送至服务器能调试呢? 二:尝试解决 直接开发机运 ...

  5. Centos7时区修改方法汇总

    方法一: timedatectl set-timezone Asia/Shanghai 方法二: 设置环境变量TZ(这个方法用得比较少,但是有一次就是这个方法帮了我大忙,其他都无法实现修改时区,特此记 ...

  6. python:将时间戳格式化为yyyyMMdd hh:mm:ss

    import time #将10位时间戳或者13位转换为时间字符串,默认为2017-10-01 13:37:04格式 def timestamp_to_date(time_stamp, format_ ...

  7. Eclipse使用Working Set

    当Eclipse中创建了太多的project,太多了,看的眼花缭乱,不好管理,也不想更换工作空间,Eclipse中 Java Working Set 工作集,可以将这些project分组,就像文件夹分 ...

  8. 一段隐藏文字的css代码,记录下

    <span style="width:1px; height:1px; color:#fff; outline-width:hidden; overflow:hidden; displ ...

  9. 理解 Node.js 的 GC 机制

    <深入浅出Node.js>第五章<内存控制>阅读笔记 随着 Node 的发展,JavaScript 的应用场景早已不再局限在浏览器中.本文不讨论网页应用.命令行工具等短时间执行 ...

  10. CentOS 5 源

    # The mirror system uses the connecting IP address of the client and the # update status of each mir ...