如何正确重写PlatformTransactionManager且不影响Spring Data JPA
问题解答
问题根因说明
Spring Batch 默认的DefaultBatchConfigurer会自动初始化DataSourceTransactionManager(JDBC 类型事务管理器),和 Spring Data JPA 依赖的JpaTransactionManager不兼容,这就是你不重写事务管理器时 Repository 无法正常工作的原因。
现有代码合理性评估
你当前的写法可以临时解决事务不兼容的问题,但存在缺陷,不是最优方案:
- 你手动实例化的
JpaTransactionManager只绑定了数据源,没有关联 Spring 容器中已经初始化好的EntityManagerFactory,会导致 JPA 持久化上下文和事务不同步,可能出现save操作提交后查询不到、一级缓存失效、脏数据等异常问题。 - 手动创建的事务管理器没有复用 Spring Boot 自动装配的配置,容易出现配置遗漏。
重写PlatformTransactionManager的最佳方式
直接注入 Spring Boot 自动配置好的JpaTransactionManager即可,Spring Boot 检测到 JPA 依赖后会自动创建该实例,已经绑定了数据源、EntityManagerFactory,且加载了所有你在配置文件中写的JPA、数据源参数,不需要手动设置任何属性,代码如下:
public class Process extends DefaultBatchConfigurer { @Autowired private PlatformTransactionManager jpaTransactionManager; @Override public PlatformTransactionManager getTransactionManager() { return jpaTransactionManager; } }
如果出于特殊需求必须手动创建JpaTransactionManager,需要额外补充EntityManagerFactory的绑定,修正后的代码如下:
public class Process extends DefaultBatchConfigurer { @Autowired private DataSource dataSource; @Autowired private EntityManagerFactory entityManagerFactory; @Override public PlatformTransactionManager getTransactionManager() { JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); jpaTransactionManager.setDataSource(dataSource); jpaTransactionManager.setEntityManagerFactory(entityManagerFactory); return jpaTransactionManager; } }
配置文件参数生效说明
数据源配置(spring.datasource.*开头的参数)
无论你用哪种重写方式,只要注入的是Spring容器管理的DataSource实例,这些配置都会正常生效,Spring初始化DataSource时已经读取了所有配置文件中的数据源参数。
JPA配置(spring.jpa.*开头的参数)
- 如果你用上面推荐的注入自动配置好的JpaTransactionManager的方式,所有JPA配置都会正常生效。
- 如果你用你原来的写法(只绑定DataSource手动创建JpaTransactionManager),这些JPA配置不会和你创建的事务管理器关联,会出现配置不生效的问题。
- 如果你用手动创建且补充绑定EntityManagerFactory的方式,JPA配置也能正常生效,因为EntityManagerFactory实例是Spring自动初始化的,已经加载了所有JPA配置。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

