@transactional仅对public方法生效,且必须由spring代理对象调用;底层依赖aop代理,非spring管理bean、private/protected/final方法、自调用(this.调用)均无效。

在 Java 中,@Transactional 是 Spring 提供的声明式事务管理核心注解,它让开发者无需手动编写开启、提交或回滚事务的代码,只需加在方法或类上,Spring 就会自动代理执行事务逻辑。
什么时候能用 @Transactional?
该注解只对 public 方法 生效,且必须由 Spring 容器管理的 Bean 调用(即不能是 this.xxx() 自调用)。底层依赖 AOP 代理,所以非 Spring 管理的对象、private/protected 方法、final 方法上添加都无效。
- 推荐加在 Service 层的具体业务方法上,而不是 Controller 或 DAO 层
- 如果加在类上,整个类所有 public 方法都默认启用事务(可被方法级注解覆盖)
- 接口上标注不生效(JDK 动态代理不识别接口上的注解)
常用属性怎么配?
事务行为主要靠几个关键属性控制:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
propagation:传播行为,默认
REQUIRED(有则加入,无则新建),常见还有REQUIRES_NEW(总是新建事务)、NEVER(不支持事务)等 -
isolation:隔离级别,默认使用数据库默认级别,可设为
ISOLATION_READ_COMMITTED等 -
rollbackFor:指定哪些异常触发回滚,默认只对
RuntimeException和Error回滚;若想对Exception子类也回滚,需显式写rollbackFor = Exception.class - noRollbackFor:指定哪些异常不回滚(即使它是运行时异常)
- timeout:事务超时时间(秒),超时自动回滚
-
readOnly:设为
true可提示数据库优化(如 MySQL 的 SELECT 不加锁),但不强制禁止写操作
为什么事务有时不生效?常见坑有哪些?
事务失效很常见,多数是因为没理解代理机制或配置疏漏:
- 自调用问题:A 方法调 B 方法,B 加了
@Transactional,但 A 是 this.b() —— 此时 B 不走代理,事务失效 - 异常被吞掉:try-catch 住异常却没重新抛出,Spring 捕获不到异常,就不会回滚
- 数据库引擎不支持事务:比如 MySQL 用了 MyISAM 表,InnoDB 才支持事务
- 未开启事务管理:忘了在配置类加
@EnableTransactionManagement,或 XML 中没配<annotation-driven></annotation-driven> - 数据源没配事务管理器:Bean 名不是
transactionManager,或没定义DataSourceTransactionManager实例
一个简单示例
假设转账业务需要原子性:
@Service
public class AccountService {
@Transactional(rollbackFor = Exception.class)
public void transfer(String from, String to, BigDecimal amount) throws Exception {
accountDao.debit(from, amount); // 扣款
// 模拟可能失败
if (amount.compareTo(BigDecimal.valueOf(1000)) > 0) {
throw new ServiceException("转账超限");
}
accountDao.credit(to, amount); // 入账
}
}
只要方法中抛出异常(包括 checked 异常),且满足 rollbackFor 条件,整个方法内的数据库操作就会回滚。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










