Spring事务传播属性

参考文献

Spring事务传播属性和隔离级别 https://www.cnblogs.com/eunice-sun/p/11024584.html

spring事务传播机制总结 https://blog.csdn.net/m18330808841/article/details/109543815

spring boot @Transactional注解事务不回滚不起作用无效 https://blog.csdn.net/zdyueguanyun/article/details/80236401?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

正文

扫盲示例

Spring事务传播属性_第1张图片

pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.12.RELEASE
         
    
    com.example
    demo-order
    0.0.1-SNAPSHOT
    demo-order
    Demo project for Spring Boot
    
        1.8
    
    
        
            mysql
            mysql-connector-java
            5.1.26
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.projectlombok
            lombok
            true
        
    

application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root

App.java

package com.example.demoorder;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

UserController.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private ServiceA serviceA;

    @GetMapping("/a")
    public void a() {
        serviceA.methodA();
    }
}

UserService.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserMapper mapper;

    //什么都不写时,默认为Propagation.REQUIRED
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        int i = 1 / 0;
    }

    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

UserMapper.java

package com.example.demoorder;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {
    @Insert("insert into a (id,name) values (#{id},#{name})")
    public void saveA(@Param("id") Integer id, @Param("name") String name);

    @Insert("insert into b (id,name) values (#{id},#{name})")
    public void saveB(@Param("id") Integer id, @Param("name") String name);
}

ServiceA.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    //@Autowired
    //private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        //serviceB.methodB();
        int i = 1 / 0;
    }
}

ServiceB.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

测试:浏览器输入 127.0.0.1:8080/a 

a表回滚成功

示例1

Propagation.REQUIRED
1.如果前面的方法已经创建了事务,那么后面的方法加入这个已存在的事务

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。

2.如果前面的方法没有创建事务,那么后面的方法会新建一个事务.

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现b表回滚成功,但是a表没有回滚。

示例2:Propagation.SUPPORTS
1如果当前存在事务,则加入当前事务

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前没有事务,就以非事务方法执行

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都不回滚。

示例3:Propagation.MANDATORY
1当前存在事务,则加入当前事务,

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        methodB();
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前事务不存在,则抛出异常。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,methodB()方法进不来,也不打印methodB字符串。

示例4 : Propagation.REQUIRES_NEW

在执行时,不论当前是否存在事务,总是会新建一个事务。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
        int i = 1 / 0;
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");

    }
}

测试:调用methodA()方法,发现a表回滚,b表插入数据库成功,b表不回滚

示例5 :Propagation.NOT_SUPPORTED

在执行时,不论当前是否存在事务,都会以非事务的方式运行。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表回滚,b表不回滚

示例6 :Propagation.NEVER

就是我这个方法不使用事务,并且调用我的方法也不允许有事务,如果调用我的方法有事务则我直接抛出异常。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NEVER)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表回滚,ServiceB的methodB不执行,不打印methodB字符串

示例7 :Propagation.NESTED

如果当前事务不存在,则像 Propagation.REQUIRED开启一个新事物
如果当前事务存在,则在嵌套事务中执行。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,b表回滚

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        try {
            serviceB.methodB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,b表回。因为调用方catch了被调方的异常,所以只有子事务回滚了。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
        int i = 1 / 0;
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

测试:调用methodA()方法,发现a表回滚,b表回滚
 

你可能感兴趣的:(Spring事务传播属性)