事务是一组操作的集合,不可以被分割。事务会把所有的操作作为一个整体,这组操作要么全部成功,要么全部失败。
事务有三种操作:
如果代码的执行逻辑是这样:
开启事务 业务A 回滚事务
此时A当中的所有操作都不会生效
开启事务 业务A 提交事务
开启事务后只有这种情况下A中的逻辑才会生效
Spring Boot对于事务操作内置了两个类,我们在使用时可以选择直接注入:
@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
//获取事务管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
//获取事务属性
@Autowired
private TransactionDefinition definition;
@Autowired
private UserMapper userMapper;
@RequestMapping("/fun1")
public void fun1() {
//获取并开启事务
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(definition);
//业务操作
//向数据库中插入一条数据
userMapper.userInsert("zhangsan","man");
//打印日志
log.info("数据插入完成");
//提交事务
dataSourceTransactionManager.commit(transaction);
}
}
@Mapper
public interface UserMapper {
@Insert("insert into userinfo(username,gender) values (#{userName},#{gender});")
void userInsert(String userName, String gender);
}
这是数据库的初始状态

代码执行后数据成功插入

@RequestMapping("/fun1")
public void fun1() {
//获取并开启事务
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(definition);
//业务操作
userMapper.userInsert("zhangsan","man");
log.info("数据插入完成");
//提交事务
// dataSourceTransactionManager.commit(transaction);
//回滚事务
dataSourceTransactionManager.rollback(transaction);
}
当代码执行成功后,数据库中的数据并没有变多。
使用注解实现事务是非常简单的只需要给需要添加事务的方法加上@Transactional注解。添加该注解后程序会自动的在方法开始前开启事务,在方法结束后提交事务;如果在方法执行中发生了没有处理的异常会自动进行回滚事务。
@Transactional既可以修饰方法也可以修饰类:
当方法正常执行完毕后会自动提交事务 :
@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
@Transactional
@RequestMapping("/fun2")
public void fun2() {
userMapper.userInsert("lisi","man");
log.info("数据插入完成");
}
}

当方法执行过程中发生异常时自动回滚事务 (该注解默认只回滚运行时异常 >和错误 发生运行时异常,事务回滚: 编译时异常不会回滚: 此时尽管程序已经报错了,可数据还是正常插入了。如何解决这个问题呢? 可以通过配置 @Transactional 注解当中的 rollbackFor 属性,通过 rollbackFor 这个属性来指定出现何种异常类型时事务进行回滚。 这个属性的类型是数组需要注意 此时error类型的错误依然会进行回滚。 使用 TransactionAspectSupport.currentTransactionStatus() 得到当前的事务,并使用setRollbackOnly使事务进行回滚 SQL中的事务隔离级别: Spring中的事务隔离级别: 事务隔离级别可以通过 @Transactional 中的 isolation 属性进行设置 如果A方法中调用B方法那么B方法是使用A方法的事务还是自己的事务,事务的传播机制就是为了解决该问题。 @Transactional 注解支持事务传播机制的设置,通过 propagation 属性来设置。 Spring 事务传播机制有 7 种(在A方法中调用B(七种传播机制都设置在该方法上)方法):@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
@Transactional
@RequestMapping("/fun2")
public void fun2() {
userMapper.userInsert("lisi111","man");
log.info("数据插入完成");
//发生运行时异常,事务回滚
throw new RuntimeException();
}
}

@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
@Transactional
@RequestMapping("/fun2")
public void fun2() throws IOException {
userMapper.userInsert("lisi111","man");
log.info("数据插入完成");
//发生编译时异常,事务不会回滚
throw new IOException();
}
}


rollbackFor
Class extends Throwable>[] rollbackFor() default {};
@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
//此时会回滚所有的Exception类型的异常
@Transactional(rollbackFor = {Exception.class})
@RequestMapping("/fun2")
public void fun2() throws IOException {
userMapper.userInsert("lisi222","man");
log.info("数据插入完成");
//此时发生编译时异常,事务回滚
throw new IOException();
}
}

@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
@Transactional(rollbackFor = {Exception.class})
@RequestMapping("/fun2")
public void fun2() {
userMapper.userInsert("lisi222","man");
log.info("数据插入完成");
//会发生栈溢出错误,仍然会回滚
while(true) {
fun2();
}
}
}

手动回滚事务
@Slf4j
@RestController
@RequestMapping("/trans")
public class Test {
@Autowired
private UserMapper userMapper;
@Transactional(rollbackFor = {Exception.class})
@RequestMapping("/fun2")
public void fun2() {
userMapper.userInsert("66666","man");
log.info("数据插入完成");
//手动设置回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}

事务隔离级别
@Transactional(isolation = Isolation.DEFAULT)
@RequestMapping("/fun2")
public void fun2() {}

事务的传播机制
@Transactional(propagation = Propagation.MANDATORY)
@RequestMapping("/fun2")
public void fun2() {}
