@Transactional 把一个方法包裹进一个数据库事务:Spring 在方法运行前开启一个事务,在方法正常返回时提交——或在它抛出异常时回滚(roll back)。底层它是一个 AOP 代理,这也是大多数陷阱的根源。
基本用法
java
{
{
accounts.debit(from, amount);
accounts.credit(to, amount);
}
}
默认情况下,Spring 只在**非受检(unchecked)**异常(RuntimeException)和 Error 上回滚——不会在受检异常上回滚。如果你抛出一个受检异常,事务会提交。要显式覆盖它:
@Transactional(rollbackFor = Exception.class) // 受检异常也回滚
public void process() throws IOException { /* ... */ }
传播决定当一个事务方法调用另一个方法时会发生什么:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void writeAuditLog(String event) { /* 独立提交 */ }
因为 @Transactional 通过代理生效,从同一个类中的另一个方法调用一个 @Transactional 方法会绕过代理——注解被悄无声息地忽略。要跨 bean 调用,或者注入 self。
事务是数据正确性所在,所以面试官会在这里紧追不放。受检异常的回滚规则和自调用 bug 是能可靠地区分用过 @Transactional 的人和理解它的人的两道题。
一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠