云计算百科
云计算领域专业知识百科平台

DeepSeek Spring事务失效场景汇总及示例

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;
    });
    }
    }

    事务失效排查清单

  • 检查方法访问修饰符 – 必须是public
  • 检查异常处理 – 确保异常正确抛出
  • 检查代理机制 – 避免自调用
  • 检查数据库支持 – 确保引擎支持事务
  • 检查配置 – @EnableTransactionManagement
  • 检查切面顺序 – 确保事务切面优先级正确
  • 检查多数据源配置 – 正确的事务管理器绑定
  • 检查传播行为 – 符合业务需求
  • 检查连接池配置 – 连接泄露会导致事务问题
  • 检查ORM框架配置 – 如Hibernate的flush模式
  • 这些示例覆盖了Spring事务失效的主要场景,实际开发中遇到的事务问题大多可以归类到这些场景中。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » DeepSeek Spring事务失效场景汇总及示例
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!