一、注解事务(声明式事务)
1. 基础配置
java
复制代码
// 启动类添加注解
@SpringBootApplication
@EnableTransactionManagement // 通常默认开启,可省略
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. 使用 @Transactional
java
复制代码
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 基本用法
@Transactional
public void createUser(User user) {
userMapper.insert(user);
// 发生异常自动回滚
}
// 指定回滚异常
@Transactional(rollbackFor = Exception.class)
public void updateUser(User user) throws Exception {
userMapper.update(user);
if (user.getAge() < 0) {
throw new Exception("年龄不能为负数");
}
}
// 不回滚指定异常
@Transactional(noRollbackFor = NullPointerException.class)
public void deleteUser(Long id) {
userMapper.delete(id);
if (id == null) {
throw new NullPointerException(); // 不会回滚
}
}
// 设置事务传播行为
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(Log log) {
// 新开事务,不受外层影响
logMapper.insert(log);
}
// 设置超时和只读
@Transactional(timeout = 30, readOnly = true)
public List<User> findAllUsers() {
return userMapper.selectAll();
}
// 隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED)
public User getUserById(Long id) {
return userMapper.selectById(id);
}
}
3. 常见传播行为
传播行为
说明
REQUIRED
默认,有事务则加入,无则新建
REQUIRES_NEW
挂起当前事务,新建事务
SUPPORTS
有事务则加入,无则非事务执行
NOT_SUPPORTED
非事务执行,挂起当前事务
MANDATORY
必须有事务,否则抛异常
NEVER
必须非事务,有事务则抛异常
NESTED
嵌套事务(Savepoint机制)
4. 注意事项
java
复制代码
// ❌ 错误:内部调用不生效
@Service
public class ServiceA {
@Transactional
public void methodA() {
methodB(); // @Transactional 不生效!
}
@Transactional
public void methodB() {}
}
// ✅ 正确:通过代理调用
@Service
public class ServiceA {
@Autowired
private ServiceA self; // 注入自身代理
@Transactional
public void methodA() {
self.methodB(); // 生效
}
@Transactional
public void methodB() {}
}
二、手动事务(编程式事务)
方式1:TransactionTemplate(推荐)
java
复制代码
@Service
public class OrderService {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private OrderMapper orderMapper;
public void createOrder(Order order) {
transactionTemplate.execute(status -> {
try {
orderMapper.insert(order);
orderMapper.updateStock(order.getProductId());
return order.getId();
} catch (Exception e) {
status.setRollbackOnly(); // 标记回滚
throw new RuntimeException("创建订单失败", e);
}
});
}
// 配置事务属性
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager manager) {
TransactionTemplate template = new TransactionTemplate(manager);
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
template.setTimeout(30);
return template;
}
// 复杂业务处理
public Result processOrder(Order order) {
return transactionTemplate.execute(status -> {
try {
// 业务逻辑1
orderMapper.insert(order);
// 条件判断手动回滚
if (order.getAmount() < 0) {
status.setRollbackOnly();
return Result.fail("金额无效");
}
// 业务逻辑2
paymentService.pay(order);
return Result.success();
} catch (Exception e) {
status.setRollbackOnly();
return Result.fail(e.getMessage());
}
});
}
}
java
复制代码
@Service
public class PaymentService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private AccountMapper accountMapper;
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// 1. 定义事务属性
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
def.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
// 2. 获取事务状态
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 扣款
accountMapper.decreaseBalance(fromId, amount);
// 加款
accountMapper.increaseBalance(toId, amount);
// 提交
transactionManager.commit(status);
} catch (Exception e) {
// 回滚
transactionManager.rollback(status);
throw new RuntimeException("转账失败", e);
}
}
// 嵌套事务示例
public void complexBusiness() {
// 外层事务
DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition();
TransactionStatus outerStatus = transactionManager.getTransaction(outerDef);
try {
// 业务A
doBusinessA();
// 内层独立事务
DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition();
innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus innerStatus = transactionManager.getTransaction(innerDef);
try {
doBusinessB();
transactionManager.commit(innerStatus);
} catch (Exception e) {
transactionManager.rollback(innerStatus);
// 内层失败不影响外层
}
transactionManager.commit(outerStatus);
} catch (Exception e) {
transactionManager.rollback(outerStatus);
throw new RuntimeException("业务失败", e);
}
}
}
三、完整示例:用户注册+发送通知
java
复制代码
@Service
public class RegisterService {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private UserMapper userMapper;
@Autowired
private NotificationService notificationService;
// 组合使用
public void register(User user) {
// 主事务:用户注册
Long userId = transactionTemplate.execute(status -> {
try {
// 保存用户
userMapper.insert(user);
// 初始化账户
accountService.initAccount(user.getId());
return user.getId();
} catch (DuplicateKeyException e) {
status.setRollbackOnly();
throw new BusinessException("用户名已存在");
}
});
// 非事务:发送通知(失败不影响注册)
try {
notificationService.sendWelcomeEmail(user.getEmail());
} catch (Exception e) {
log.error("发送邮件失败", e);
}
}
// 混合使用
@Transactional
public void registerWithCoupon(User user, Coupon coupon) {
// 声明式事务
userMapper.insert(user);
// 手动事务:发放优惠券(独立事务)
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.execute(status -> {
try {
couponService.giveCoupon(user.getId(), coupon);
return true;
} catch (Exception e) {
log.error("发放优惠券失败", e);
status.setRollbackOnly();
return false;
}
});
// 注册失败不影响优惠券发放
if (user.getAge() < 0) {
throw new IllegalArgumentException("年龄无效");
}
}
}
四、配置详解
bash
复制代码
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
# 事务配置
transaction:
default-timeout: 30 # 默认超时时间
rollback-on-commit-failure: true # 提交失败回滚
java
复制代码
@Configuration
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager manager) {
return new TransactionTemplate(manager);
}
// 配置多数据源事务
@Bean
public PlatformTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource ds) {
return new DataSourceTransactionManager(ds);
}
@Bean
public PlatformTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource ds) {
return new DataSourceTransactionManager(ds);
}
}
五、选择建议
场景
推荐方式
简单CRUD
@Transactional
复杂业务逻辑
TransactionTemplate
需要细粒度控制
PlatformTransactionManager
多数据源
手动指定事务管理器
测试环境
@Transactional + @Rollback
六、常见问题
java
复制代码
// 1. 事务不生效:方法必须是public
@Transactional // private 不生效
private void method() {}
// 2. 异常被捕获不抛出不回滚
@Transactional
public void method() {
try {
// 业务
} catch (Exception e) {
// 不抛出 -> 不回滚,需要手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
// 3. 默认只回滚RuntimeException,需要指定
@Transactional(rollbackFor = Exception.class)
以上涵盖了Spring Boot中事务的主要使用方式,建议优先使用@Transactional,需要更灵活控制时使用TransactionTemplate。