1、以下是事物的传播机制:
@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
换句话说,使用当前的事务,如果当前没有事务,则自己新建一个事务,
子方法是必须运行在一个事务中的,如果当前存在事务,则加入这个事务,成为一个整体
@Transactional(propagation=Propagation.SUPPORTS)
如果当前有事务,则使用事务,如果当前没有事务,则不使用事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.NESTED)
父子嵌套事务,父事务发生错误回滚,子方法如果是嵌套事务,则一起回滚。
相反,如果子方法发生错误,在父方法try catch后,父方法则不不需要一起回滚。
2、代码验证说明:
2.1 无任何事务
// service层
public interface StuService {
public void saveParent();
public void saveChildren();
}
// service实现类
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
//测试service接口及实现类
public interface TransTest {
public void testPropagationTrans();
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
// 单元测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class) //配置启动类
public class Test {
@Autowired
private TransTest transTest;
@org.junit.Test
public void myTest(){
transTest.testPropagationTrans();
}
}
结果:
2.2 测试Propagation.REQUIRED
2.2.1 父方法有Propagation.REQUIRED
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果: 数据库未新增任何数据。
2.2.2 子方法有Propagation.REQUIRED
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.3 Propagation.SUPPORTS
2.3.1子方法SUPPORTS,父方法无事务
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.3.2 子方法SUPPORTS,父方法REQUIRD
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRD)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果: 数据库无任何新增。
2.4 Propagation.MANDATORY
2.4.1 子方法有MANDATORY,父方法无事务
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果抛出异常:
2.4.2 子方法有MANDATORY,父方法有有REQUIRD
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:数据库无任何变化。
2.5 Propagation.REQUIRES_NEW
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:因为其新启动了一个事务,因此,子方法失败,父方法是另一个事务,接收到子方法的失败后,自身也失败,数据库无任何新增数据。
2.6 Propagation.NOT_SUPPORTED
2.6.1 子Propagation.NOT_SUPPORTED,父无
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.6.2 子Propagation.NOT_SUPPORTED,父Propagation.REQUIRD
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRD)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.7 Propagation.NEVER
2.7.1 子Propagation.NEVER,父Propagation.REQUIRD
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.NEVER)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRD)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.7.2 子Propagation.NEVER,父无
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.NEVER)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果:
2.8 Propagation.NESTED
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Override
public void saveParent(){
Stu stu = new Stu();
stu.setAge(19);
stu.setName("parent");
stuMapper.insert(stu);
}
@Override
@Transactional(propagation = Propagation.NESTED)
public void saveChildren(){
saveChild1();
int a = 1/0;
saveChild2();
}
public void saveChild1(){
Stu stu1 = new Stu();
stu1.setName("child-1");
stu1.setAge(11);
stuMapper.insert(stu1);
}
public void saveChild2(){
Stu stu2 = new Stu();
stu2.setName("child-2");
stu2.setAge(22);
stuMapper.insert(stu2);
}
}
@Service
public class TransTestImpl implements TransTest {
@Autowired
private StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void testPropagationTrans() {
stuService.saveParent();
stuService.saveChildren();
}
}
结果: 无任何数据。 即,如果当前有事务,则开启子事务(嵌套事务),嵌套事务是独立提交或者回滚;如果当前没有事务,则同REQUIRD。
3、为什么不需要手动开启@Enabletransactionmanagement
在spring boot项目中,注解@SpringBootApplication在加载容器的时候,已经将开启事务管理的功能了,不需要额外添加注解