解析 Spring 中用于事务管理的核心注解 @Transactional,以及在代码中捕获异常时,该注解的作用如何变化。
chou403
/ Spring
/ c:
/ u:
/ 5 min read
Spring事务管理注解用的哪个?如果代码里捕获了异常,这个注解还有用么
在 Spring 中,事务管理通常通过 @Transactional
注解来实现。@Transactional
注解用于声明方法或类中的所有方法都在事务上下文中执行。Spring 事务管理器会自动处理这些方法的事务边界(即事务的开始和结束)。
使用 @Transactional
注解
基本使用
将 @Transactional
注解放在类上或方法上,以声明它们应在事务上下文中执行:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Transactional
public void createUser(User user) {
// 方法体中的代码将在事务中执行
}
}
高级使用
@Transactional
注解提供了一些属性来控制事务行为:
propagation
:定义事务的传播行为,例如REQUIRED
(默认值),REQUIRES_NEW
等。isolation
:定义事务的隔离级别,例如READ_COMMITTED
,REPEATABLE_READ
等。timeout
:定义事务的超时时间(秒)。readOnly
:如果为true
,表示事务只读。rollbackFor
:定义哪些异常会触发事务回滚。noRollbackFor
:定义哪些异常不会触发事务回滚。
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, timeout = 30, readOnly = false, rollbackFor = {Exception.class})
public void createUser(User user) {
// 方法体中的代码将在事务中执行
}
异常处理对事务的影响
Spring 的默认事务管理策略是在方法抛出未检查异常(RuntimeException 或 Error)时回滚事务。受检异常(Checked Exception)不会触发事务回滚,除非明确配置。
捕获异常对事务的影响
如果代码捕获了异常,并且没有重新抛出异常,事务管理器将不会检测到异常,也不会触发回滚。如下示例:
@Transactional
public void createUser(User user) {
try {
// 业务逻辑
} catch (Exception e) {
// 捕获异常,事务不会回滚
e.printStackTrace();
}
}
在这种情况下,即使发生异常,由于异常被捕获,事务也不会回滚。要解决这个问题,可以显式地回滚事务:
显式回滚事务
-
使用
TransactionAspectSupport
:import org.springframework.transaction.interceptor.TransactionAspectSupport; @Transactional public void createUser(User user) { try { // 业务逻辑 } catch (Exception e) { // 手动回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); e.printStackTrace(); } }
-
重新抛出异常:
另一种方法是在捕获异常后重新抛出,这样事务管理器可以检测到异常并回滚事务:
@Transactional public void createUser(User user) { try { // 业务逻辑 } catch (Exception e) { // 重新抛出异常,触发回滚 throw new RuntimeException(e); } }
-
指定
rollbackFor
属性:如果希望在受检异常发生时也回滚事务,可以使用
rollbackFor
属性:@Transactional(rollbackFor = Exception.class) public void createUser(User user) { try { // 业务逻辑 } catch (Exception e) { // 捕获受检异常 e.printStackTrace(); throw e; // 重新抛出异常,触发回滚 } }
总结
@Transactional
注解 用于声明方法或类中的所有方法在事务上下文中执行。- 异常捕获对事务的影响: 默认情况下,未检查异常会触发事务回滚,但受检异常不会。捕获异常会阻止事务管理器检测到异常,从而阻止事务回滚。
- 显式回滚事务: 可以使用
TransactionAspectSupport
进行手动回滚,或在捕获异常后重新抛出异常,确保事务管理器检测到异常并回滚事务。