文章参考了此博客: 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. linux删除文件的前n行

    需求描述: 今天看了一个系统的临时文件,有5.6G的大小,这个文件也没有用了,想要将大部分的文件都删除掉. 在此记录下删除的过程.删除前n行的记录. 操作过程: 对于数据量比较大的情况(本例5800万 ...

  2. Java基础 awt Graphics2D 生成矩形图片并向其中画一条直线

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  3. .netcore linq更改list实体对象中的字段 批量条件

    List<cs_orders> orderlist = _ordersRepository.WhereLoadEntityEnumerable(p => p.order_status ...

  4. XML读写工具

    import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import j ...

  5. ufw防火墙规则不生效

    正式站系统是Ubuntu 16.04.6 一.今天一个项目有百度爬出,在nginx中封掉还在一直爬取,都403还不停爬取 二.在uwf封掉爬出ip,想封掉80端口没有用,然后封掉整个网段还是没有用,尴 ...

  6. Linux下配置Golang开发环境

    前几天无意间看到了微信推送的golang开发的消息,看到golang那么牛逼,突然心血来潮想学习一下go.工欲善其事必先利其器,想做go开发,必须先配置好go的开发环境(就像开发Java先安装配置jd ...

  7. c#之break和continue的区别

    break:跳出循环,执行循环外的语句: continue:跳出此次循环,进入下一次循环:

  8. 【LOJ2292】[THUSC2016]成绩单(区间DP)

    题目 LOJ2292 分析 比较神奇的一个区间 DP ,我看了很多题解都没看懂,大约是我比较菜罢. 先明确一下题意:abcde 取完 c 后变成 abde ,可以取 bd 这样取 c 后新增的连续段. ...

  9. Java 中不允许使用静态局部变量

    Java 中不允许使用静态局部变量

  10. 后端&前端零碎知识点和注意问题

    后端 1. Spring自带的MD5加密工具类 import org.springframework.util.DigestUtils; String md5Password = DigestUtil ...