数据表结构:
package com.ybqdren.service; import com.ybqdren.pojo.Stu; public interface StuService { public Stu getStuInfo(int id); public void saveStu(); public void saveStu(int id); public void updateStu(int id); public void deleteStu(int id); public void saveParent(); public void saveChildren(); }
2. StuServiceImpl
package com.ybqdren.service.impl; import com.ybqdren.mapper.StuMapper; import com.ybqdren.pojo.Stu; import com.ybqdren.service.StuService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class StuServiceImpl implements StuService { @Autowired private StuMapper stuMapper; //@Transactional(propagation = Propagation.SUPPORTS) @Override public Stu getStuInfo(int id) { return (Stu) stuMapper.selectByPrimaryKey(id); } //@Transactional(propagation = Propagation.REQUIRED) @Override public void saveStu() { Stu stu = new Stu(); stu.setName("jack"); stu.setAge(18); stuMapper.insert(stu); } // @Transactional(propagation = Propagation.REQUIRED) @Override public void saveStu(int id) { } //@Transactional(propagation = Propagation.REQUIRED) @Override public void updateStu(int id) { Stu stu = new Stu(); stu.setId(id); stu.setName("lucy"); stu.setAge(20); stuMapper.updateByPrimaryKey(stu); } //@Transactional(propagation = Propagation.REQUIRED) @Override public void deleteStu(int id) { stuMapper.deleteByPrimaryKey(id); } @Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Override public void saveChildren() { saveChild1(); } public void saveChild1(){ Stu stu1 = new Stu(); stu1.setName("child-1"); stu1.setAge(11); stuMapper.insert(stu1); } public void saveChild2(){ Stu stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); } }
3. TestTransService
package com.ybqdren.service; public interface TestTransService { public void testPropagationTrans(); }
4. TestTransServiceImpl
package com.ybqdren.service.impl; import com.ybqdren.service.StuService; import com.ybqdren.service.TestTransService; 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 TestTransServiceImpl implements TestTransService { @Autowired private StuService stuService; // @Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); } }
5. TransTest
import com.ybqdren.Application; import com.ybqdren.service.StuService; import com.ybqdren.service.TestTransService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest(classes = Application.class) public class TransTest { @Autowired private StuService stuService; @Autowired private TestTransService testTransService; @Test public void myTest() { testTransService.testPropagationTrans(); } }
二、不使用事务 1. StuServiceImpl
package com.ybqdren.service.impl; import com.ybqdren.mapper.StuMapper; import com.ybqdren.pojo.Stu; import com.ybqdren.service.StuService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class StuServiceImpl implements StuService { @Autowired private StuMapper stuMapper; // ..... @Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); 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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); } }
2. TestTransServiceImpl
package com.ybqdren.service.impl; import com.ybqdren.service.StuService; import com.ybqdren.service.TestTransService; 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 TestTransServiceImpl implements TestTransService { @Autowired private StuService stuService; // @Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); // 新增 stuService.saveChildren(); } }
3. *** 作执行后的数据库 1) 报异常
可以看到saveChildren只保存了一数据,child-2并没有插入进去
在发生异常后,child-2是无法保存到数据库的,也没有进行回滚
三、事务 1. REQUIRED 1)简介
- 使用当前的事务,如果当前没有事务,则自己新建一个事务,子方法是必须运行在一个事务中的;
- 如果当前存在事务,则加入这个事务,成为一个整体。
2)在父方法中添加 在TestTransServiceImpl中开启事务
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
执行后
可以看到,此处数据库中并没有插入数据
因为在此处进行了事务传播REQUIRED,虽然saveParent和saveChild方法都没有事务,但是它们也传播到了REQUIRED事务
所以当父方法使用REQUIRED事务时,子方法发生异常后,两个子方法中的事务都会进行回滚
3)在单个子方法中添加 清除父方法上的事务
// @Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
在saveChild方法上添加一个事务
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.REQUIRED) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
可以看到saveParent方法执行的数据添加到了数据库,而saveChild没有。
也就是说,当前的整个方法方法体中不带有事务时,他回去重新创建一个事务
也就是说saveChildren方法必须要存在于某个事务中去运行,所以它发生异常后进行了回滚,而saveParent没有事务。
2. SUPPORTS 1)简介
如果当前有事务,则使用事务;如果当前没有事务,则不使用事务。
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.SUPPORTS) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.SUPPORTS) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
前后都为空
3. MANDATORY 1)简介
该传播属性强制必须存在一个事务,如果不存在,则抛出异常。
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.MANDATORY) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后 控制台报错
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.MANDATORY) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
4. REQUIRES_NEW 1)简介
- 如果当前有事务,则挂起该事务,并且自己创建一个新的事务给自己使用;
- 如果当前没有事务,则同 REQUIRED。
2)外层无事务,子方法有事务,而父方法没有事务
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.REQUIRES_NEW) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
saveParent没有事务,而saveChildren有事务,所以会将后者和前者 *** 作区分开来,后者发生错误会进行回滚,但是前者会正常存储到数据库中。
3)外层有事务,子方法有事务,父方法没有事务
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.REQUIRES_NEW) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
数据库
前后都为空。
分析
@Transactional(propagation = Propagation.REQUIRES_NEW) @Override public void saveChildren() { saveChild1(); int a = 1/0; saveChild2(); }
saveChildren方法执行后会产生1个byzero的异常,而这个异常会传递给其调用方法:
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
因为当前方法有事务REQUIRED,变成了一个整体,所以就会影响当前方法中一起被调用的saveParent,所以也导致saveParent也出现了回滚。
4)外层使用事务也产生异常,子方法有事务,父方法没有事务
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); int a = 1/0; }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.REQUIRES_NEW) @Override public void saveChildren() { saveChild1(); saveChild2(); } public void saveChild1(){ Stu stu1 = new Stu(); stu1.setName("child-1"); stu1.setAge(11); stuMapper.insert(stu1); } public void saveChild2(){ Stu stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
多了两条数据:
因为子方法saveChildren中使用了新的事务,所以当前事务是被挂起的,所以当前方法的事务是不会影响到其子方法的:
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); int a = 1/0; }
但是saveParent中没有使用事务,所以会被回滚,所以数据库中会保存saveChildren中插入的值:
子方法和外层都是用REQUIRED事务,也就是两个方法都使用同一个事务:
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); int a = 1/0; }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.REQUIRED) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
没有插入值:
两个方法都共用了同一个事务,所以不管在哪个方法中抛出异常,都会进行回滚。
5. NOT_SUPPORTED 1)简介
如果当前有事务,则把事务挂起,自己不使用事务去运行数据库 *** 作。
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NOT_SUPPORTED) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
数据库
虽然控制台有报异常,但是并没有进行回滚:
外层没有事务,且子方法中也不使用事务,因此产生了异常也没有进行回滚。
3)外层有事务,子方法不使用事务,父方法没有事务
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NOT_SUPPORTED) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
数据库
saveChildren方法中抛出了一个异常,所以只执行到了saveChild1():
@Transactional(propagation = Propagation.NOT_SUPPORTED) @Override public void saveChildren() { saveChild1(); int a = 1/0; saveChild2(); }
而因为当前方法是不使用异常的,所以saveChild1是没有发生回滚的。
而调用方是本身有事务的:
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
所以从saveChildren中产生的异常,也会让此处同时被调用的saveParent方法被回滚。
6. NEVER 1)简介
如果当前有事务存在,则抛出异常。
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NEVER) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
提示已经有事务存在的异常:
数据库
没有任何数据插入:
@Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NEVER) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
数据库
没有事务,就没有相应的回滚。
7. NESTED 1)简介
- 如果当前有事务,则开启子事务(嵌套事务),嵌套事务是独立提交或者回滚;如果当前没有事务,则同 REQUIRED。
- 但是如果主事务提交,则会携带子事务一起提交。
- 如果主事务回滚,则子事务会一起回滚。相反,子事务异常,则父事务可以回滚或不回滚。
2)外层使用REQUIRED事务有异常,子方法使用NESTED事务无异常
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); stuService.saveChildren(); int a = 1/0; }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NESTED) @Override public void saveChildren() { saveChild1(); saveChild2(); } public void saveChild1(){ Stu stu1 = new Stu(); stu1.setName("child-1"); stu1.setAge(11); stuMapper.insert(stu1); } public void saveChild2(){ Stu stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
数据库
什么都没有:
有父子嵌套事务存在话,在调用方法中发生的异常,那么在嵌套事务里面的事务也会被回滚。
3)外层使用REQUIRED事务无异常,子方法使用NESTED事务有异常
@Transactional(propagation = Propagation.REQUIRED) @Override public void testPropagationTrans() { stuService.saveParent(); try{ // save point 保存点: 对当前事务的异常进行catch之后,就不会影响同层次调用的其他方法 其他 *** 作 stuService.saveChildren(); }catch (Exception e){ e.printStackTrace(); } }
@Override public void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setAge(19); stuMapper.insert(stu); } @Transactional(propagation = Propagation.NESTED) @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 stu1 = new Stu(); stu1.setName("child-2"); stu1.setAge(11); stuMapper.insert(stu1); }
执行后
使用save point 将saveChildren方法中的异常隔离开,不会影响到当前调用方中其他的方法。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)