• 事务机制:
  1. Datasource => 获取一个 connection
  2. connection.setAutocommit(false);
  3. 执行 SQL
  4. connection.commit();

TransactionInterceptor执行流程

Spring 中的事务 - 图1

传播机制:

Propagation.REQUIRED(默认机制)

  1. @Transactional
  2. public void test1() {
  3. userMapper.insert1(new User("张三"));
  4. userService.test2();
  5. }
  6. @Transactional
  7. public void test2() {
  8. userMapper.insert2(new User("李四"));
  9. }

_

当前线程上面是不是有事务,如果有,并且是Propagation.REQUIRED 就不会从新开启事务,而是包括在原有事务之内

  1. Datasource => 获取一个 connection => 保存至 ThreadLocal
  2. connection.setAutocommit(false);
  3. ThreadLocal.get() => 执行 SQL
  4. ThreadLocal.get() => 执行另一个包含 SQL 的业务逻辑
  5. connection.commit();

Propagation.REQUIRES_NEW

  1. @Transactional
  2. public void test1() {
  3. userMapper.insert1(new User("张三"));
  4. userService.test2();
  5. }
  6. @Transactional(propagation = Propagation.REQUIRES_NEW)
  7. public void test2() {
  8. userMapper.insert2(new User("李四"));
  9. }

_

当前线程上面是不是有事务,如果有,并且是 Propagation.REQUIRES_NEW 就会将原来的事务挂起,并开启新的事务去执行新的逻辑,然后恢复原来的事务,提交原来的事务

  1. Datasource => 获取一个 connection1 => 保存至 ThreadLocal
  2. connection1.setAutocommit(false);
  3. ThreadLocal.get() => connection1 => 执行 SQL
  4. 继续向下执行
  5. 发现 Propagation.REQUIRES_NEW
  6. 将 connection1 挂机(从 ThreadLocal 中移除,并保存到其他地方)
  7. Datasource => 获取一个 connection2 => 保存至 ThreadLocal
  8. connection2.setAutocommit(false);
  9. ThreadLocal.get() => connection2 => 执行另一个包含 SQL 的业务逻辑
  10. connection2.commit()
  11. 将 connection1 恢复(从新保存到 ThreadLocal 中)
  12. connection1.commit();

Propagation.NESTED

  1. @Transactional
  2. public void test1() {
  3. userMapper.insert1(new User("张三"));
  4. userService.test2();
  5. }
  6. @Transactional(propagation = Propagation.NESTED)
  7. public void test2() {
  8. userMapper.insert2(new User("李四"));
  9. }

当前线程上面是不是有事务,如果有,并且是 Propagation.NESTED 就会在当前位置设置一个 savepoint,然后继续执行,如果出现了异常,只会回滚到 savepoint 这里,然后继续执行,直到提交

  1. Datasource => 获取一个 connection => 保存至 ThreadLocal
  2. connection.setAutocommit(false);
  3. ThreadLocal.get() => 执行 SQL
  4. ThreadLocal.get() => 执行另一个包含 SQL 的业务逻辑
  5. 继续向下执行
  6. 发现 Propagation.NESTED
  7. 设置一个 savepoint
  8. ThreadLocal.get() => 执行 SQL
  9. 如果发现异常,则回滚到 savepoint
  10. 继续向下执行
  11. connection.commit();

Propagation.NEVER

  1. @Transactional
  2. public void test1() {
  3. userMapper.insert1(new User("张三"));
  4. userService.test2();
  5. }
  6. @Transactional(propagation = Propagation.NEVER)
  7. public void test2() {
  8. userMapper.insert2(new User("李四"));
  9. }

当前线程上面是不是有事务,如果有,并且是 Propagation.NEVER 就会直接抛异常