Spring Batch执行更新操作时抛出InvalidDataAccessApiUsageException问题排查
错误原因分析与解决办法
核心原因
这个TransactionRequiredException本质是执行更新/删除SQL时,当前上下文没有绑定有效的事务,主要由以下几点导致:
1. 事务管理器不匹配
你的Batch配置类中使用了DataSourceTransactionManager,这是JDBC层面的事务管理器,但JPA操作(包括你的Repository更新方法)需要JpaTransactionManager来管理EntityManager的事务上下文。两者不匹配会导致JPA无法识别当前的事务,执行更新时就会抛出无事务的异常。
2. @Transactional注解未生效
虽然你的Repository接口上加了@Transactional,但由于事务管理器不匹配,Spring无法为该Repository创建正确的事务代理。另外,Spring Batch的Chunk处理本身会开启事务,如果自定义的事务注解传播行为(默认REQUIRED)无法正确加入Batch的事务上下文,也会导致更新操作脱离事务。
3. @Modifying查询的事务依赖
JPA的@Modifying注解标记的更新/删除查询,强制要求在事务环境下执行。如果当前没有可用的事务上下文(比如事务管理器不匹配导致事务未绑定),就会触发这个异常。
解决步骤
1. 替换事务管理器为JpaTransactionManager
修改BatchBean中的事务管理器配置,使用JPA对应的事务管理器:
@Configuration public class BatchBean { // ... 其他配置 @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } // 确保JobRepository使用这个JpaTransactionManager @Bean public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception { JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean(); jobRepositoryFactoryBean.setDataSource(dataSource); jobRepositoryFactoryBean.setTransactionManager(transactionManager); jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED"); jobRepositoryFactoryBean.afterPropertiesSet(); return jobRepositoryFactoryBean.getObject(); } }
2. 调整@Transactional的使用方式
- 可以去掉Repository上的
@Transactional,转而在Spring Batch的Step组件(比如ItemWriter)上添加@Transactional,确保更新操作在Batch的事务上下文内执行。 - 如果保留Repository上的注解,建议明确指定事务传播属性:
@Transactional(propagation = Propagation.REQUIRED) @Repository public interface ApprovedTrxSummaryRepo extends JpaRepository<ApprovedTrxSummery, Long> { @Modifying @Query(value = "update approved_trx_summery set STATUS = 2 where STATUS= 44 and TRANSACTION_REFERENCE = ?1", nativeQuery = true) void updateSegmentedTransaction(String transactionReference); }
3. 验证Batch事务上下文一致性
确保Spring Batch的JobRepository、Step使用的事务管理器和JPA操作的事务管理器是同一个,避免出现多个事务管理器导致的上下文隔离问题。
内容的提问来源于stack exchange,提问作者Enamul Haque
相关产品推荐
相关产品推荐

