事务管理
事务概念
什么是事务
事务是一组操作的逻辑单元,要么全部成功,要么全部失败。
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开发能力。