关于controller的异常处理及service层的事务控制方式

目录
  • controller异常处理及service层的事务控制
  • controller层Exception异常事务回滚失效问题
    • Spring的@Transactional源码中写道
    • 测试①
    • 测试②
    • 测试③
    • 测试④

controller异常处理及service层的事务控制

最近写代码涉及到一些事务,上午终于把代码给理顺了,之前不太清楚在哪里做异常处理,导致代码遍地try-catch,相当难看。

还是基于controller-service-dao三层来写代码,从入口开始,controller层的方法对应的是某个url,面向的是应用人员,应该返回他们能读懂的信息,所以controller必须做异常处理,一般来说会有统一的异常处理方法;

service层面向的是controller,service层中的某些方法,必须保证其事务,所以在service层进行事务控制是相当必要的,对于多条sql进行事务控制,如果某个sql执行失败,那么应当对已经执行的sql语句进行回滚;

dao层更多是单一的sql语句,没有必要进行事务控制,因为事务开销并不便宜(官方原话);

基于以上三点,回头再思考关于异常的处理,一般情况应该把异常网上抛,一直抛到最终处理的那一层,所以对于dao层和service其实是没有必要进行try-catch的,直接往上抛异常就可以。

与之对应的,是spring的事务配置,默认情况下,spring只对运行时异常进行回滚,如果在dao层处理了异常,那么需要进行额外的配置,spring才会对异常进行回滚,常用的配置是@Transactional(rollbackFor=Exception.class)

顺便提一个java知识点,关于try-catch-finally中,finally的作用,finally设计之初就是为了关闭资源,如果在finally中使用return语句,会覆盖try或者catch的返回值,最常见的就是覆盖异常,即便catch往上抛了异常,也会被覆盖,返回finally中return语句的返回值。

controller层Exception异常事务回滚失效问题

Spring的@Transactional源码中写道

By default, a transaction will be rolling back on {@link RuntimeException}and {@link Error} but not on checked exceptions (business exceptions).

默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。

测试①

默认spring事务只在发生未被捕获的 RuntimeException 时才回滚。

// 测试回滚成功案例,基于IllegalArgumentException(RuntimeException)实现回滚
@GetMapping("/testSuccess")
@Transactional// 如果不加,就不会回滚
public R testSuccess(@RequestParam("type") Integer type){
    eduTeacherService.removeById("2");
    if (type == 1){
        throw new IllegalArgumentException("测试回滚成功案例!");
    }
    eduTeacherService.removeById("3");
    return  R.ok();
}

测试②

Exception异常,事务回滚失败;

// 测试回滚失败案例,基于Exception实现回滚;
@GetMapping("/testFail")
@Transactional
public R testFail(@RequestParam("type") Integer type)  {
    try {
        eduTeacherService.removeById("2");
        if (type == 1){
            throw new Exception("测试回滚失败案例!");
        }
        eduTeacherService.removeById("3");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return  R.ok();
}

测试③

用rollbackFor解决Exception不进行事务回滚

rollbackFor = Exception.class + throws Exception
@GetMapping("/testFailRollbackFor")
// 配置rollbackFor
@Transactional(propagation= Propagation.REQUIRED,rollbackFor = Exception.class)
public R testFailRollbackFor(@RequestParam("type") Integer type) throws Exception {
        eduTeacherService.removeById("2");
        if (type == 1){
            throw new Exception("测试回滚失败rollbackFor成功案例!");
        }
        eduTeacherService.removeById("3");
    return  R.ok();
}

测试④

手动回滚解决Exception不进行事务回滚

catch:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@GetMapping("/testSuccessByHand")
@Transactional
public R testSuccessByHand(@RequestParam("type") Integer type)  {
    try {
        eduTeacherService.removeById("2");
        if (type == 1){
            throw new Exception("测试回滚失败案例!");
        }
        eduTeacherService.removeById("3");
    } catch (Exception e) {
        e.printStackTrace();
        //手动回滚,如果sql2()抛了异常,sql1()会回滚,不影响事物正常执行
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
    return  R.ok();
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • springboot多个service互相调用的事务处理方式

    目录 多个service互相调用的事务处理 注解配置如下 Spring事务调用Service和Service之间的调用 原理解析 多个service互相调用的事务处理 今天,想在一个service的方法A中,调用另一个service的方法B,方法A和方法B均存在数据库插入操作,并且@Transaction注解也都加了,但是当B方法中抛出异常时,A中的插入语句还是能够执行成功. 注解配置如下 @Transactional(isolation= Isolation.DEFAULT,propagati

  • 关于Controller层和Service层的类报错问题及解决方案

    目录 Controller层和Service层的类报错 Controller层和Service层的作用 1.在controller和service里都写那些代码? 2.在整个项目中什么时候加异常?异常怎么处理? Controller层和Service层的类报错 当出现以下这种情况的时候,可以看看pom.xml文件中是否少了jar包. 当我出现这种情况的时候,我去看pom.xml包发现,如不其然我少了一个jar包 这就是我少了的那个jar包(spring-web),把这个加上之后就可以了. <!-

  • spring在service层的方法报错事务不会回滚的解决

    目录 spring在service层方法报错事务不会回滚 解决方法 service手动回滚问题 spring在service层方法报错事务不会回滚 @Transactional(rollbackFor = {Exception.class}) public void insertData() throws Exception {     // 业务代码1     business1();          // 业务代码2     business2();          // 业务代码3  

  • 浅谈controller中调用多个service方法的问题

    目录 controller调用多个service方法 controller调用service中方法的一些事物问题 controller调用多个service方法 一般service方法是有事务的,把所有操作封装在一个service方法中是比较安全的. 如果在controller中调用多个service方法,只有查询的情况下是可以这样的. controller调用service中方法的一些事物问题 关于在开发过程中的事务传播的一个问题: controller 调用service中a方法,a方法没有

  • 关于MVC的dao层、service层和controller层详解

    目录 MVC的dao层.service层和controller层 1.dao层 2.service层 3.controller层 4.view层 5.它们之间的关系 关于dao层/mapper层的一些笔记 1.BaseMapper 2.@mapper MVC的dao层.service层和controller层 1.dao层 dao层主要做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,dao层的设计首先是设计dao层的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可以

  • 关于controller的异常处理及service层的事务控制方式

    目录 controller异常处理及service层的事务控制 controller层Exception异常事务回滚失效问题 Spring的@Transactional源码中写道 测试① 测试② 测试③ 测试④ controller异常处理及service层的事务控制 最近写代码涉及到一些事务,上午终于把代码给理顺了,之前不太清楚在哪里做异常处理,导致代码遍地try-catch,相当难看. 还是基于controller-service-dao三层来写代码,从入口开始,controller层的方法

  • winfrom 在业务层实现事务控制的小例子

    复制代码 代码如下: try    { using (TransactionScope tr = new TransactionScope()) {     int i = this.customermanager.addCustomer(customer);     int j = this.homestatusmanager.updateHomestatus(homestatus);     if ((i * j) > 0)     {  MessageBox.Show("记录插入成功

  • 结合Service层讲解DAO层的异常处理操作

    domain:只是定义一个javabean. dao:对于数据库的操作,都放到dao层,也就是dao里面通常是对数据库的增.删.改.查等操作. service:完成相应的业务逻辑处理,调用dao层. (web)servlet:完成界面请求.对界面进行跳转等等.servlet调用service层. 例子: 在domain包中,新建Xxx.java:在dao包中,新建IXxxDAO.java:在impl包中,新建XxxDAOImpl类:在test包中,新建XxxDAOTest.java,在XxxDA

  • 如何让CI框架支持service层

    大家知道CodeIgniter框架式MVC分层的,通常大家把业务逻辑写到Controller中,而Model只负责和数据库打交道. 但是随着业务越来越复杂,controller越来越臃肿,举一个简单的例子,比如说用户下订单,这必然会有一系列的操作:更新购物车.添加订单记录.会员添加积分等等,且下订单的过程可能在多种场景出现,如果这样的代码放controller中则很臃肿难以复用,如果放model会让持久层和业务层耦合.现在公司的项目就是,很多人将一些业务逻辑写到model中去了,model中又调

  • Java service层获取HttpServletRequest工具类的方法

    大家都知道 能在Controller/action层获取HttpServletRequest ,但是这里给大家备份的是从代码内部service层获取HttpServletRequest工具类. 具体如下: package com.base.common.sessionutils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframewo

  • 自定义注解和springAOP捕获Service层异常,并处理自定义异常操作

    一 自定义异常 /** * 自定义参数为null异常 */ public class NoParamsException extends Exception { //用详细信息指定一个异常 public NoParamsException(String message){ super(message); } //用指定的详细信息和原因构造一个新的异常 public NoParamsException(String message, Throwable cause){ super(message,

  • SpringBoot在自定义类中调用service层等Spring其他层操作

    背景: 做了一个TCP服务器来接入智能设备,然后需要将设备实时发送的定位等关键信息存储到数据库. 为了考虑将来可能对外提供rest接口,采用将TCP服务器集成到SpringBoot框架,当然,也是为了能最快利用mybatis框架实现数据访问,然后依次解决了如何启动,如何注销等各种问题,然后在TCP服务器消息处理时,需要写数据库,直接调用DAO层,编译报错. 改为调用Service层,编译正常,运行到调用的地方,报空指针异常,跟踪到异常位置,发现service为空,也就是按照之前controlle

  • springboot实现在工具类(util)中调用注入service层方法

    一.新建BeanUtil类 import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.Applic

随机推荐