
Spring 事务属性详解Spring 的Transactional注解提供了一组属性用来精确控制事务的行为。这些属性决定了事务如何传播、隔离级别、超时时间、是否只读以及哪些异常触发回滚。一、事务属性总览属性类型默认值作用propagationPropagationREQUIRED事务传播行为isolationIsolationDEFAULT事务隔离级别timeoutint-1不超时事务超时时间秒readOnlybooleanfalse是否只读事务rollbackForClass[]{}触发回滚的异常类型rollbackForClassNameString[]{}触发回滚的异常类名noRollbackForClass[]{}不触发回滚的异常类型noRollbackForClassNameString[]{}不触发回滚的异常类名二、传播行为propagation传播行为定义了事务方法被调用时如何与当前已有事务交互。这是事务属性中最核心、最复杂的一个。传播行为说明适用场景REQUIRED默认。当前有事务则加入没有则新建绝大多数业务方法REQUIRES_NEW挂起当前事务新建独立事务日志记录、审计操作NESTED当前有事务则嵌套执行保存点没有则新建部分回滚场景SUPPORTS当前有事务则加入没有则以非事务执行查询方法NOT_SUPPORTED以非事务方式执行挂起当前事务不需要事务的操作MANDATORY必须在已有事务中执行否则抛异常强制要求事务的方法NEVER必须以非事务方式执行否则抛异常禁用事务的方法Transactional(propagationPropagation.REQUIRED)publicvoidcreateOrder(Orderorder){orderDao.save(order);}最常用的两个// 主业务加入或新建事务Transactional(propagationPropagation.REQUIRED)publicvoidplaceOrder(Orderorder){}// 日志独立事务即使主业务回滚日志也要保留Transactional(propagationPropagation.REQUIRES_NEW)publicvoidsaveLog(Stringmessage){}三、隔离级别isolation隔离级别定义了事务之间的数据可见性解决并发事务的脏读、不可重复读、幻读问题。隔离级别脏读不可重复读幻读DEFAULT使用数据库默认——READ_UNCOMMITTED可能可能可能READ_COMMITTED不会可能可能REPEATABLE_READ不会不会可能SERIALIZABLE不会不会不会Transactional(isolationIsolation.READ_COMMITTED)publicUsergetUser(Longid){returnuserDao.findById(id);}注意DEFAULT表示使用底层数据库的默认隔离级别。MySQL InnoDB 默认是REPEATABLE_READOracle 默认是READ_COMMITTED。四、超时时间timeout事务允许执行的最大时间单位是秒。超时后事务自动回滚。Transactional(timeout30)publicvoidbatchProcess(ListOrderorders){// 超过 30 秒自动回滚}默认值-1表示不超时由数据库自己决定。超时时间不是精确的实际超时可能略有偏差因为检查时机由数据库或框架决定。五、只读事务readOnly标记事务为只读用于优化查询性能。Transactional(readOnlytrue)publicListUserfindAll(){returnuserMapper.selectAll();}只读事务的作用数据库可以做一些优化如不记录回滚日志。提示框架和数据库这个事务不会修改数据。某些数据库驱动会对只读事务做特殊处理。注意readOnly true并不保证一定会阻止写操作。如果只读事务中执行了INSERT、UPDATE、DELETE行为取决于数据库实现可能报错也可能静默执行。六、回滚规则Spring 事务默认只在遇到RuntimeException和Error时回滚。检查型异常Exception的子类不会触发回滚。rollbackFor指定哪些异常触发回滚。Transactional(rollbackFor{BusinessException.class,SQLException.class})publicvoidprocessOrder(Orderorder)throwsBusinessException{// 抛出这些异常时回滚}rollbackForClassName用类名字符串指定效果与rollbackFor相同。Transactional(rollbackForClassName{com.example.BusinessException})noRollbackFor指定哪些异常不触发回滚。Transactional(noRollbackFor{BusinessException.class})publicvoidprocessOrder(Orderorder)throwsBusinessException{// 抛出 BusinessException 时不回滚}noRollbackForClassName用类名字符串指定不触发回滚的异常。Transactional(noRollbackForClassName{com.example.BusinessException})最佳实践默认回滚规则只覆盖RuntimeException。如果业务中会抛出检查型异常务必显式指定rollbackFor Exception.class避免异常被吞掉但数据已提交。Transactional(rollbackForException.class)publicvoidcreateOrder(Orderorder)throwsIOException{// 抛出 IOException 时也回滚}七、完整示例ServicepublicclassOrderService{AutowiredprivateOrderDaoorderDao;AutowiredprivateInventoryDaoinventoryDao;AutowiredprivateLogServicelogService;Transactional(propagationPropagation.REQUIRED,isolationIsolation.READ_COMMITTED,timeout30,readOnlyfalse,rollbackFor{BusinessException.class,SQLException.class},noRollbackFor{NotifyException.class})publicvoidcreateOrder(Orderorder)throwsBusinessException,SQLException{orderDao.save(order);inventoryDao.decrease(order.getProductId(),order.getQuantity());// 日志用独立事务即使主业务回滚日志也保留logService.saveLog(创建订单order.getId());}}八、属性配置方式对比配置方式示例适用场景注解属性Transactional(propagation ...)方法或类级别XML 配置tx:adviceaop:config老项目编程式TransactionTemplate需要动态控制事务边界九、常见问题1. 默认回滚规则不覆盖检查型异常Transactionalpublicvoidprocess()throwsIOException{// IOException 是检查型异常默认不回滚// 需要 rollbackFor Exception.class}2. 传播行为选择不当导致数据不一致// ❌ 日志用 REQUIRED主业务回滚时日志也回滚Transactional(propagationPropagation.REQUIRED)publicvoidsaveLog(Stringmsg){}// ✅ 日志用 REQUIRES_NEW主业务回滚日志仍保留Transactional(propagationPropagation.REQUIRES_NEW)publicvoidsaveLog(Stringmsg){}3. 只读事务中执行写操作Transactional(readOnlytrue)publicvoidupdateUser(Useruser){userDao.update(user);// 可能报错也可能静默执行}4. 超时时间设置过短Transactional(timeout1)publicvoidbatchProcess(){// 批量操作可能超过 1 秒导致意外回滚}5. 隔离级别与数据库默认不一致// MySQL 默认 REPEATABLE_READ显式设置为 READ_COMMITTED 可能改变行为Transactional(isolationIsolation.READ_COMMITTED)十、总结属性核心作用默认值常用值propagation事务传播行为REQUIREDREQUIRED、REQUIRES_NEWisolation事务隔离级别DEFAULTREAD_COMMITTED、REPEATABLE_READtimeout超时时间秒-130readOnly是否只读false查询方法设truerollbackFor触发回滚的异常RuntimeExceptionException.classnoRollbackFor不触发回滚的异常{}业务异常事务属性是Transactional精确控制事务行为的核心。传播行为决定事务如何嵌套隔离级别决定并发时的数据可见性超时时间防止事务长期占用资源只读标记优化查询性能回滚规则决定哪些异常触发回滚。理解这些属性的含义和使用场景才能写出正确、高效的事务代码。