Skip to content

事务管理

事务概念

什么是事务

事务是一组操作的逻辑单元,要么全部成功,要么全部失败。

ACID特性

特性说明
原子性(Atomicity)事务是不可分割的工作单位
一致性(Consistency)事务必须使数据库从一个一致性状态变换到另一个一致性状态
隔离性(Isolation)多个事务并发执行时,一个事务的执行不应影响其他事务的执行
持久性(Durability)一个事务一旦提交,它对数据库中数据的改变就是永久性的

@Transactional注解

基本使用

java
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
    }
}

注解属性

java
@Transactional(
    propagation = Propagation.REQUIRED,      // 传播行为
    isolation = Isolation.READ_COMMITTED,    // 隔离级别
    timeout = 30,                            // 超时时间(秒)
    readOnly = false,                        // 是否只读
    rollbackFor = Exception.class,           // 回滚异常类型
    noRollbackFor = BusinessException.class  // 不回滚异常类型
)
public void transfer(Long fromId, Long toId, BigDecimal amount) {
    // 业务逻辑
}

事务传播行为

七种传播行为

传播行为说明
REQUIRED(默认)有事务就加入,没有就新建
SUPPORTS有事务就加入,没有就以非事务运行
MANDATORY必须在事务中运行,否则抛异常
REQUIRES_NEW新建事务,挂起当前事务
NOT_SUPPORTED以非事务运行,挂起当前事务
NEVER以非事务运行,有事务则抛异常
NESTED嵌套事务

示例

java
@Service
public class UserService {
    
    // REQUIRED:默认行为
    @Transactional
    public void method1() {
        // 有事务就加入,没有就新建
    }
    
    // REQUIRES_NEW:总是新建事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void method2() {
        // 总是新建事务,挂起外层事务
    }
    
    // NESTED:嵌套事务
    @Transactional(propagation = Propagation.NESTED)
    public void method3() {
        // 嵌套事务,可独立回滚
    }
}

事务隔离级别

五种隔离级别

隔离级别脏读不可重复读幻读
DEFAULT---
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE

示例

java
@Service
public class UserService {
    
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User getUser(Long id) {
        return userRepository.findById(id);
    }
    
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void updateUser(User user) {
        userRepository.update(user);
    }
}

事务回滚规则

默认规则

  • 默认只对RuntimeException和Error回滚
  • 受检异常(checked exception)不回滚

自定义回滚规则

java
@Service
public class UserService {
    
    // 指定回滚异常
    @Transactional(rollbackFor = Exception.class)
    public void method1() throws Exception {
        // 所有Exception都回滚
    }
    
    // 指定不回滚异常
    @Transactional(noRollbackFor = BusinessException.class)
    public void method2() {
        // BusinessException不回滚
    }
}

编程式事务

使用TransactionTemplate

java
@Service
public class UserService {
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Autowired
    private UserRepository userRepository;
    
    public void createUser(User user) {
        transactionTemplate.execute(status -> {
            try {
                userRepository.save(user);
                // 其他操作
            } catch (Exception e) {
                status.setRollbackOnly();
            }
            return null;
        });
    }
    
    public User getUser(Long id) {
        return transactionTemplate.execute(status -> {
            return userRepository.findById(id);
        });
    }
}

使用PlatformTransactionManager

java
@Service
public class UserService {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    public void createUser(User user) {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            userRepository.save(user);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

事务失效场景

1. 方法不是public

java
@Service
public class UserService {
    
    @Transactional
    private void method() {  // 事务失效
    }
}

2. 同类方法调用

java
@Service
public class UserService {
    
    public void method1() {
        method2();  // 事务失效,因为不走代理
    }
    
    @Transactional
    public void method2() {
    }
}

解决方案:

java
@Service
public class UserService {
    
    @Autowired
    private UserService self;  // 注入自己
    
    public void method1() {
        self.method2();  // 走代理
    }
    
    @Transactional
    public void method2() {
    }
}

3. 异常被捕获

java
@Service
public class UserService {
    
    @Transactional
    public void method() {
        try {
            // 业务逻辑
        } catch (Exception e) {
            // 异常被捕获,事务不回滚
        }
    }
}

4. 数据库不支持事务

某些数据库或存储引擎不支持事务。

下一步

继续学习 Spring MVC基础,了解Spring的Web开发能力。