Spring JDBC与事务管理7:Spring声明式事务二:事务传播方式;

本文详细介绍Spring中的事务传播行为,通过案例演示七个传播模式(REQURIED, REQURIES_NEW, NOT_SUPPORTED等),帮助理解事务嵌套和控制策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明: 

(1)在【Spring JDBC与事务管理6:Spring声明式事务一:声明式事务配置;】 中,我们知道propagation属性设置为“REQURIED”就是开启声明式事务;但是,对于propagation属性的详细内容并不了解;所以,本篇博客就来详细介绍下事务传播行为的内容;

(2)在实际开发中,我们很少去设置事务传播方式(行为);只是,在面试的时候可能会被问到;所以,本篇博客的内容就作为一个扩展知识吧;

(3)本篇博客的代码沿用自【Spring JDBC与事务管理6:Spring声明式事务一:声明式事务配置;】;

目录

一:事务传播行为简介

二:为演示【事务传播行为】,而准备的案例;

(1)创建BatchService类:该类里,添加了两个新增的方法;

(2)修改EmployeeService类:增加BatchService属性,并调用BatchService中的方法;

(3)在IoC容器中配置BatchService对象;在EmployeeService对象中注入BatchService对象;设置BatchService两个方法的事务传播方式;

三:初始演示一:【事务传播行为】初体验;

(1)情况说明:

(2)测试、运行

(3)分析

四:【事务传播行为】的七种类型;

1.七种【事务传播行为】;

2.summary 


一:事务传播行为简介

(1)事务传播行为:可以使用XML的方式配置;

(2) 事务传播行为:也可以使用注解的方式配置;【使用注解方式,开发声明式事务】在下篇博客中会介绍;

(3)这儿不懂【事务传播行为】没事,接下来的案例会更好的说明;


二:为演示【事务传播行为】,而准备的案例;

代码沿用自【Spring JDBC与事务管理6:Spring声明式事务一:声明式事务配置;】;

(1)创建BatchService类:该类里,添加了两个新增的方法;

package com.imooc.spring.jdbc.service;

import com.imooc.spring.jdbc.dao.EmployeeDao;
import com.imooc.spring.jdbc.entity.Employee;

import java.util.Date;

public class BatchService {
    private EmployeeDao employeeDao;
    public void importJob1() {
        for (int i = 1; i <= 10; i++) {
            Employee employee = new Employee();
            employee.setEno(8000 + i);
            employee.setEname("研发部员工" + i);
            employee.setSalary(4000f);
            employee.setDname("研发部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }
    public void importJob2() {
        for (int i = 1; i <= 10; i++) {
            Employee employee = new Employee();
            employee.setEno(9000 + i);
            employee.setEname("市场部员工" + i);
            employee.setSalary(4500f);
            employee.setDname("市场部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }

    public EmployeeDao getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }
}

 说明:

(1)在实际项目中,业务肯定会很复杂,自然会有很多业务方法;而自然,也会有很多新增、修改删除的业务方法。而这类新增操作的业务方法,都是需要进行事务控制的;

(2)BatchService类的主要的功能就是批量导入;

(3)比如,BatchService类中的,inportJob1()和importJob2()这两个新增的方法,按理说都是需要进行业务控制的;

(2)修改EmployeeService类:增加BatchService属性,并调用BatchService中的方法;

package com.imooc.spring.jdbc.service;

import com.imooc.spring.jdbc.dao.EmployeeDao;
import com.imooc.spring.jdbc.entity.Employee;
import java.util.Date;

public class EmployeeService {
    private EmployeeDao employeeDao;
    private BatchService batchService;

    public void batchImport() {
        for (int i = 1; i <= 10; i++) {
//            if (i == 3) {
//                throw new RuntimeException("一个意料之外的异常。");
//            }
            Employee employee = new Employee();
            employee.setEno(8000 + i);
            employee.setEname("员工" + i);
            employee.setSalary(4000f);
            employee.setDname("市场部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }

    /**
     * 调用BatchService这个【批量导入类】的批量导入方法;
     */
    public void startImportJob() {
        batchService.importJob1();
        batchService.importJob2();
    }

    public EmployeeDao getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }

    public BatchService getBatchService() {
        return batchService;
    }

    public void setBatchService(BatchService batchService) {
        this.batchService = batchService;
    }
}

说明:

(1)在EmployeeService类中,新增了startImportJob()方法,该方法中,调用了BatchService类中的方法;

(2)为了能实现(1)中的需求,在EmployeeService类中增加了BatchService属性,并添加对应的get和set方法;

(3)在IoC容器中配置BatchService对象;在EmployeeService对象中注入BatchService对象;设置BatchService两个方法的事务传播方式;


三:初始演示一:【事务传播行为】初体验;

(1)情况说明:

(2)测试、运行

(3)分析

可以发现,上面涉及到了方法的嵌套调用;如果代码正常运行、没有出现问题,其结果看着是OK的;但是,在实际开发中上面这种配置是有问题的;

因为,importJob1()和importJob2(),只需要各自保证自己就行了;这两个方法之间应该互不影响;如下:

  

  

……………………………………………………

即可以发现,importJob1()、importJob2(),startImportJob()三个方法是嵌套调用的;然后,三个方法的事务传播方式均设置成了“REQURIED”;此时,通过运行结果可以发现,importJob1()、importJob2()是一荣俱荣、一损俱损的,二者并没有做到互不影响;


四:【事务传播行为】的七种类型;

1.七种【事务传播行为】;

(1)【REQURIED】:事务传播行为的默认值:如果我们不设置事务传播方式,那么就默认是【REQURIED】;

           ● 当【设置了事务的方法】进行嵌套时,如果【外侧方法】有事务,那么【内侧被调用的方法】就会加入到外侧方法的事务中;如下图所示:

           ● 【REQURIED】详细分析;

(2)【REQURIES_NEW】:方法会创建新的事务;

           ● 【REQURIES_NEW】:即便【外侧方法】有事务,【内侧被调用的方法】依旧会给自己创建一个新事务;如下案例演示;

然后,重新运行;

           ● 【REQURIES_NEW】:详细分析;

(3)【NOT_SUPPORTED】:如果【外侧方法】设置了事务,则把当前事务挂起,以非事务方式执行【内侧被调用的方法】;这种策略无法保证数据的完整性,不太安全;

(4)【SUPPORTS】:如果【外侧方法】设置了事务,【内侧被调用的方法】就用这个事务;如果没有事务,就不使用事务;因为,【新增、修改、删除】不使用事务会存在风险,所以这种无法保证数据的完整性,不太安全;

(5)【MANDATORY】:如果【外侧方法】设置了事务,【内侧被调用的方法】就用这个事务;如果【外侧方法】没有设置事务,就报错;

PS:mandatory:n:受托者;adj:强制性的; 强制的; 法定的; 义务的; 

(6)【NEVER】:如果【外侧方法】设置了事务,就报错;如果【外侧方法】没有设置事务,【内侧被调用的方法】就以非事务方式执行;这个几乎不用;

(7)【NESTED】:如果【外侧方法】设置了事务,【内侧被调用的方法】就用这个事务;如果【外侧方法】没有设置事务,【内侧被调用的方法】就采用【REQURIED】的方式;

…………………………………………………… 

2.summary 

     ● 根据不同的业务需求,设置不同的事务传播行为;在实际开发中,【REQURIED】、【REQURIES_NEW】、【NOT_SUPPORTED】使用较多;

     ● 日常开发中,大多数我们使用【REQURIED】,因为我们一般要保证一个Service方法中的内容要么全部OK,要么什么也不做;

     ● 少部分情况下,使用【REQURIES_NEW】;

     ● 【NOT_SUPPORTED】多用于查询方法上;仔细一想,因为【新增、修改、删除】存在出错的风险,一旦出错其事务就会回滚;如果,【新增、修改删除】和【查询】混合在一起时,【NOT_SUPPORTED】可以把【查询】从【整体的潜在的回滚风险】中,拎出来;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值