SpringBoot事务回滚
springBoot自动实现事务回滚
springBoot事务管理代码实现:
主启动类:注解@EnableTransactionManagement,开启事务管理
application.yaml配置文件:mysql 8.x 配置信息
spring:
datasource: # mysql数据库连接
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&characterEncoding=utf-8
username: root
password: root
初始表数据:
业务类:
UserService类:
//@Transactional 先注释
public R saveUser(User user) {
//新增用户信息
userMapper.insert(user);
//代码异常
int i = 1 / 0;
UserDetail userDetail = new UserDetail();
userDetail.setUserId(user.getId());
userDetail.setQq(String.valueOf(System.currentTimeMillis()).substring(0, 10));
//新增用户详情信息
userDetailMapper.insert(userDetail);
user.setUserDetail(userDetail);
return R.ok().data("user", user);
}
测试类:
@SpringBootTest
class SpringApplyApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
User user = new User();
user.setUser("likelong");
user.setBalance(10000);
userService.saveUser(user);
}
}
测试结果:
数据库只有用户信息表有数据,用户详情表没有数据,这是有问题的
user_table表
user_detail表
删除用户表中数据,解除注解@Transactional注释,重新测试。
此时没有任何问题,两张表中都没有任何数据。这是因为项目业务代码抛出异常,被springBoot捕获到,springBoot帮我们进行了数据库的回滚操作。
如果我们不抛出异常而是进行异常捕获会发生什么呢。修改UserService业务代码如下:
@Service
@Slf4j
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserDetailMapper userDetailMapper;
@Transactional
public R saveUser(User user) {
//捕获异常
try {
userMapper.insert(user);
//代码异常
int i = 1 / 0;
UserDetail userDetail = new UserDetail();
userDetail.setUserId(user.getId());
userDetail.setQq(String.valueOf(System.currentTimeMillis()).substring(0, 10));
userDetailMapper.insert(userDetail);
user.setUserDetail(userDetail);
return R.ok().data("user", user);
} catch (Exception e) {
log.error("新增用户出现异常~");
e.printStackTrace();
}
return null;
}
}
再次测试:事务回滚失效,会有上述相同的问题 – 数据库只有用户信息表有数据,用户详情表没有数据。
springBoot手动触发事务回滚
再次删除库中数据,修改代码测试:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();手动触发事务回滚
@Service
@Slf4j
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserDetailMapper userDetailMapper;
@Transactional
public R saveUser(User user) {
try {
userMapper.insert(user);
//代码异常
int i = 1 / 0;
UserDetail userDetail = new UserDetail();
userDetail.setUserId(user.getId());
userDetail.setQq(String.valueOf(System.currentTimeMillis()).substring(0, 10));
userDetailMapper.insert(userDetail);
user.setUserDetail(userDetail);
return R.ok().data("user", user);
} catch (Exception e) {
log.error("新增用户出现异常~");
//手动触发事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
return null;
}
}
手动触发事务回滚,数据正常,两个表格都没有数据。一切正常。
注意事项:
- 抛出的异常不要catch ,否则相当于没有异常。导致无法自动回滚。
- 如果通过抛出异常的方法来回滚。方法中的后续代码就不会再执行。如果用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 手动触发回滚,则方法中的后续代码还会执行。
总结:
想要让springBoot帮助我们实现数据库事务回滚,我们业务代码尽量不要catch我们的异常,要是真的需要捕获或者是没有异常发生,需要事务回滚,可以手动触发事务回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()【方法上的 @Transactional依旧不能少】。