Spring事务失效场景汇总及示例
我将为您整理Spring事务失效的常见场景,并提供相应的代码示例。实际上,100种场景更多是概念性的分类,我将核心场景归类为以下10大类,每类包含多种具体情形。
一、方法访问权限问题
1.1 非public方法的事务失效
@Service
public class UserService {
@Transactional
private void privateMethod() {
// 事务不会生效
userRepository.save(new User());
throw new RuntimeException("测试异常");
}
@Transactional
protected void protectedMethod() {
// 事务不会生效
userRepository.save(new User());
}
@Transactional
void defaultMethod() {
// 事务不会生效
userRepository.save(new User());
}
}
1.2 static静态方法
@Service
public class StaticService {
@Transactional
public static void staticMethod() {
// 事务不会生效 – Spring AOP无法代理静态方法
jdbcTemplate.update("INSERT INTO users VALUES (?)", "test");
}
}
二、自调用问题
2.1 同一类内部方法调用
@Service
public class SelfInvocationService {
public void outerMethod() {
// 直接调用内部事务方法,事务失效
innerTransactionalMethod();
}
@Transactional
public void innerTransactionalMethod() {
userRepository.save(new User());
throw new RuntimeException("事务不会回滚");
}
}
2.2 私有方法自调用
@Service
public class PrivateSelfInvocationService {
@Transactional
public void publicMethod() {
// 调用私有方法,事务可能失效
privateMethod();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
private void privateMethod() {
// 私有方法上的@Transactional无效
userRepository.save(new User());
}
}
三、异常处理问题
3.1 异常被捕获未抛出
@Service
public class ExceptionHandlingService {
@Transactional
public void catchException() {
try {
userRepository.save(new User());
throw new RuntimeException("业务异常");
} catch (Exception e) {
// 异常被捕获,事务不会回滚
log.error("错误被处理", e);
}
}
}
3.2 默认只回滚RuntimeException
@Service
public class CheckedExceptionService {
@Transactional
public void checkedException() throws Exception {
userRepository.save(new User());
// 默认配置下,受检异常不会触发回滚
throw new Exception("受检异常");
}
@Transactional(rollbackFor = Exception.class)
public void rollbackForAll() throws Exception {
userRepository.save(new User());
// 配置rollbackFor后,受检异常会触发回滚
throw new Exception("受检异常,但会回滚");
}
}
3.3 错误的异常类型指定
@Service
public class WrongExceptionService {
@Transactional(rollbackFor = IOException.class)
public void wrongRollbackFor() {
userRepository.save(new User());
// 抛出RuntimeException,但rollbackFor指定了IOException
throw new RuntimeException("不会触发回滚");
}
}
四、传播行为配置问题
4.1 REQUIRES_NEW在自调用中失效
@Service
public class PropagationService {
@Transactional
public void outerMethod() {
userRepository.save(new User("user1"));
try {
// 自调用,REQUIRES_NEW不会生效
innerMethod();
} catch (Exception e) {
log.error("内部方法异常", e);
}
// outerMethod的事务不会因为innerMethod异常而回滚
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerMethod() {
userRepository.save(new User("user2"));
throw new RuntimeException("innerMethod异常");
}
}
4.2 NOT_SUPPORTED传播行为
@Service
public class NotSupportedService {
@Transactional
public void transactionalMethod() {
userRepository.save(new User("user1"));
// 切换到非事务环境执行
nonTransactionalMethod();
throw new RuntimeException("事务会回滚吗?");
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void nonTransactionalMethod() {
// 在非事务环境下执行
userRepository.save(new User("user2"));
// 此处异常不会影响外层事务
}
}
五、数据库/数据源相关问题
5.1 MySQL MyISAM引擎不支持事务
— 使用MyISAM引擎的表不支持事务
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
) ENGINE=MyISAM;
5.2 多数据源事务管理器配置错误
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource primaryDataSource() {
// 主数据源
return DataSourceBuilder.create().build();
}
@Bean
public DataSource secondaryDataSource() {
// 从数据源
return DataSourceBuilder.create().build();
}
// 错误:只配置了一个事务管理器
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(primaryDataSource());
// secondaryDataSource的事务将无法管理
}
}
5.3 手动提交事务
@Service
public class ManualCommitService {
@Autowired
private DataSource dataSource;
@Transactional
public void manualCommitInTransaction() {
Connection conn = null;
try {
conn = dataSource.getConnection();
// 手动设置自动提交,破坏Spring事务管理
conn.setAutoCommit(true);
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO users VALUES (1, 'test')");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
六、AOP代理相关问题
6.1 非Spring代理对象调用
@Service
public class NonProxyService {
@Transactional
public void transactionalMethod() {
userRepository.save(new User());
}
public void test() {
// 错误:直接new对象调用,不是Spring代理对象
NonProxyService service = new NonProxyService();
service.transactionalMethod(); // 事务失效
}
}
6.2 final方法无法被代理
@Service
public class FinalMethodService {
@Transactional
public final void finalMethod() {
// final方法无法被CGLIB代理,事务失效
userRepository.save(new User());
}
}
6.3 非Spring管理Bean中的@Transactional
// 没有@Component、@Service等注解
public class NonSpringBean {
@Autowired
private UserRepository userRepository;
@Transactional // 完全无效
public void saveUser() {
userRepository.save(new User());
}
}
七、编程式事务使用问题
7.1 混合声明式和编程式事务
@Service
public class MixedTransactionService {
@Autowired
private PlatformTransactionManager transactionManager;
@Transactional
public void mixedTransaction() {
// 声明式事务开始
TransactionStatus status = transactionManager.getTransaction(
new DefaultTransactionDefinition()
);
try {
userRepository.save(new User("user1"));
// 编程式事务提交
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
// 声明式事务可能异常
userRepository.save(new User("user2"));
throw new RuntimeException("声明式事务回滚");
}
}
八、嵌套事务相关问题
8.1 NESTED传播在非支持数据库失效
@Service
public class NestedPropagationService {
@Transactional
public void nestedTransaction() {
userRepository.save(new User("user1"));
// MySQL某些版本不支持保存点
innerNestedMethod();
}
@Transactional(propagation = Propagation.NESTED)
public void innerNestedMethod() {
userRepository.save(new User("user2"));
throw new RuntimeException("嵌套事务回滚");
}
}
九、异步/多线程问题
9.1 @Async与@Transactional混用
@Service
public class AsyncTransactionService {
@Async
@Transactional
public void asyncTransactional() {
// 事务可能失效,因为异步方法在新线程执行
userRepository.save(new User());
}
}
9.2 新线程中操作数据库
@Service
public class MultiThreadService {
@Transactional
public void mainMethod() {
userRepository.save(new User("main-thread"));
new Thread(() -> {
// 新线程中的数据库操作不在事务中
userRepository.save(new User("sub-thread"));
}).start();
}
}
十、配置相关问题
10.1 未启用事务管理
@SpringBootApplication
// 缺少@EnableTransactionManagement注解
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
10.2 AOP切面顺序问题
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE) // 切面优先级高于事务切面
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
// 这个切面可能捕获异常,影响事务回滚
try {
return joinPoint.proceed();
} catch (Exception e) {
log.error("记录日志", e);
throw e; // 如果这里不重新抛出,事务不会回滚
}
}
}
解决方案和最佳实践
@Service
public class CorrectTransactionService {
@Autowired
private CorrectTransactionService self; // 注入自身以解决自调用问题
public void businessMethod() {
// 通过self调用,确保AOP代理生效
self.transactionalMethod();
}
@Transactional(rollbackFor = Exception.class)
public void transactionalMethod() {
// 业务逻辑
userRepository.save(new User());
}
}
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public TransactionInterceptor transactionInterceptor(
PlatformTransactionManager transactionManager) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionManager(transactionManager);
Properties props = new Properties();
props.setProperty("*", "PROPAGATION_REQUIRED,-Exception");
interceptor.setTransactionAttributes(props);
return interceptor;
}
}
@Configuration
public class MultiDataSourceConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "primaryTransactionManager")
@Primary
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Component
public class TransactionTemplateService {
@Autowired
private TransactionTemplate transactionTemplate;
public void executeInTransaction() {
transactionTemplate.execute(status -> {
// 业务逻辑
userRepository.save(new User());
return null;
});
}
public void executeWithSettings() {
TransactionTemplate template = new TransactionTemplate(
transactionTemplate.getTransactionManager()
);
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
template.execute(status -> {
// 业务逻辑
return null;
});
}
}
事务失效排查清单
这些示例覆盖了Spring事务失效的主要场景,实际开发中遇到的事务问题大多可以归类到这些场景中。
网硕互联帮助中心




评论前必须登录!
注册