事务传播方式:dao和service层都在接口处增加了transactional,都有自动处理事务的能力,形成(两个以上的事务才能传播)事务传播(一共有其中事务传播行为)。外层service调的dao,dao层不会开启一个新的事务,共用一个事务,service层包dao,整体提交回滚。
1. @Transactional(propagation = Propagation.REQUIRED)
@Transactional(propagation = Propagation.REQUIRED)//默认(必填)
代码举例:内部创建两个对象并放入数据库;
Service接口:
void addTwo()
Service实现类:
public void addTwo() { //插入第一个对象 Student s1 = new Student(); s1.setName("张三"); s1.setAge(22); studentDao.insert(s1); //故意报错,如果单独处理,第一个对象则会插入成功; //但是因为用的整体事务传播,则两个对象都插入不成功,会整体回滚 String str = null; str.length(); //插入第二个对象 Student s2 = new Student(); s2.setName("李四"); s2.setAge(25); studentDao.insert(s2); }
@Test public void test(){ studentService.addTwo(); }
2. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {NullPointerException.class, IOException.class})
@Transactional注解,默认回滚条件为方法内部抛出运行期异常RuntimeException(没有被我们自行捕获);rollbackFor为自行指定在这些异常出现时才回滚。(出问题的回滚,没出问题的继续提交)。
@Transactional(propagation = Propagation.REQUIRED, rollbackFor {NullPointerException.class, IOException.class})
上述代码示例中,/故意报错,如果单独处理,第一个对象则会插入成功;但是因为用的整体事务传播,则两个对象都插入不成功,会整体回滚。
3. @Transactional(propagation=Propagation.NOT_SUPPORTED)
在Service接口上加入此注解,意为service层不进行事务处理,但内部dao层还具有自身自动事务处理的能力(外层挂起,内层起效果)。
表现结果:上面增加两个对象的代码中,在报空指针异常时,第一个对象仍然可以进入数据库。
4.总结
dao层只管底层数据的增删改查;service层各种业务处理(可以注入各种dao,拼接底层的高级业务处理)(可以用于套餐的处理)。
4.1 例子:转账
service层中一个方法包含两个修改(不同对象),整体提交
4.2 注意:事务处理两边导致质变
例子:(人多,人少时,部分人的信息出现错误)
(人少时)导excel整体回滚,修改后,整体回滚,重新导入,之前的人也需要删掉;
(人多时)业务层中写了一个循环,出现非重要错误,trycatch直接将错误抛出,之前的信息仍然插入。