实践是检验真理的唯一标准!
验证==>@Transactional只能回滚运行时异常,不能回滚受检异常。如果要回滚受检异常请使用@Transactional(rollbackFor=Exception.class)同时需要抛出异常
1、验证 ==> @Transactional只能回滚运行时异常
写个controller
package com.springboot.study.demo1.controller;
import com.springboot.study.demo1.entity.User;
import com.springboot.study.demo1.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
*@program: springboot_study
*@description:
*@author: yinkai
*@create: 2020-03-01 13:00
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Resource
private UserService userService;
@RequestMapping("/test1")
public void test(){
userService.insertUser(new User(14L,"OK",10,"[email protected]",123));
}
}
在UserServiceImpl中添加方法,上面添加@Transactional注解
在插入一条数据之后,出现除0异常(是一种运行时异常)
@Transactional
@Override
public Boolean insertUser(User user){
//插入user记录
boolean save = save(user);
//然后出现运行时异常
int i = 1/0;
return save;
}
启动工程,访问http://localhost:8080/test/test/test1 程序报错后插入数据失败,数据回滚;
2、验证 ==> @Transactional不能回滚受检异常
将方法做如下修改,使用空字符串构造file对象,然后调用其createNewFile()方法。该方法会抛出IOException (是一种受检异常)
@Transactional
@Override
public Boolean insertUser(User user){
//插入user记录
boolean save = save(user);
//然后出现运行时异常
File file = new File("");
try {
boolean newFile = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return save;
}
启动工程,访问http://localhost:8080/test/test/test1 程序报错后插入数据成功,事务没有得到回滚。如下
3、验证==> 如果要回滚受检异常请使用@Transactional(rollbackFor=Exception.class)同时需要抛出异常
在service的insertUser方法中对IOException 异常进行try/catch 同时抛出异常
@Transactional(rollbackFor= Exception.class)
@Override
public Boolean insertUser(User user) throws IOException {
//插入user记录
boolean save = save(user);
//然后出现运行时异常
File file = new File("");
try {
boolean newFile = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
//抛出异常
throw e;
}
return save;
}
回滚成功,表中没有新插入的记录
那如果不抛出呢?事务会回滚吗?
@Transactional(rollbackFor= Exception.class)
@Override
public Boolean insertUser(User user) throws IOException {
//插入user记录
boolean save = save(user);
//然后出现运行时异常
File file = new File("");
try {
boolean newFile = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return save;
}
果然,如果不抛出异常。只是service层内部消化掉。是没办法回滚的
若只抛出异常,不设置rollbackFor= Exception.class属性,那么事务遇到受检异常会得到回滚吗?
@Transactional
@Override
public Boolean insertUser(User user) throws IOException {
//插入user记录
boolean save = save(user);
//然后出现运行时异常
File file = new File("");
try {
boolean newFile = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
//抛出异常
throw e;
}
return save;
}
没有得到回滚~ 事实证明 抛出异常和设置rollbackFor= Exception.class两者缺一不可
所以这条结论是正确的~
验证==>使用api的形式手动回滚
上面验证了@Transactional注解不加rollbackFor= Exception.class属性和不在方法内抛出受检异常则事务不会回滚;但是其实还有一种手动回滚的方式。如下
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@Transactional
@Override
public Boolean insertUser(User user) {
//插入user记录
boolean save = save(user);
//然后出现运行时异常
File file = new File("");
try {
boolean newFile = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}finally {
//手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return save;
}
事务回滚!手动回滚的方式可行~ 但是出于代码的优雅性。这种方式不予考虑使用
@Transactional不建议使用在接口上。如果切面使用cjlib实现的话则事务无效
先开个坑,等有时间再来验证
@Transactional申明的service实现类的方法必须要在对应service接口中有对应的抽象方法
一个serviceImpl 实现类方法就必须对应一个service接口的抽象方法